// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "system_diagnostics_directory.h"

#include <lib/syslog/cpp/macros.h>

#include <algorithm>

#include <fs/pseudo_file.h>

#include "debug_info_retriever.h"
#include "lib/fit/promise.h"
#include "lib/inspect/cpp/inspector.h"
#include "lib/inspect/cpp/value_list.h"
#include "src/lib/fxl/strings/string_printf.h"

using fxl::StringPrintf;

namespace {
struct ThreadInfo {
  zx_koid_t koid;
  fbl::String name;
  zx::thread thread;
  int64_t runtime;
};

static constexpr size_t kMaxThreads = 2048;

const char* obj_type_get_name(zx_obj_type_t type) {
  switch (type) {
    case ZX_OBJ_TYPE_NONE:
      return "none";
    case ZX_OBJ_TYPE_PROCESS:
      return "process";
    case ZX_OBJ_TYPE_THREAD:
      return "thread";
    case ZX_OBJ_TYPE_VMO:
      return "vmo";
    case ZX_OBJ_TYPE_CHANNEL:
      return "channel";
    case ZX_OBJ_TYPE_EVENT:
      return "event";
    case ZX_OBJ_TYPE_PORT:
      return "port";
    case ZX_OBJ_TYPE_INTERRUPT:
      return "interrupt";
    case ZX_OBJ_TYPE_PCI_DEVICE:
      return "pci_device";
    case ZX_OBJ_TYPE_LOG:
      return "log";
    case ZX_OBJ_TYPE_SOCKET:
      return "socket";
    case ZX_OBJ_TYPE_RESOURCE:
      return "resource";
    case ZX_OBJ_TYPE_EVENTPAIR:
      return "eventpair";
    case ZX_OBJ_TYPE_JOB:
      return "job";
    case ZX_OBJ_TYPE_VMAR:
      return "vmar";
    case ZX_OBJ_TYPE_FIFO:
      return "fifo";
    case ZX_OBJ_TYPE_GUEST:
      return "guest";
    case ZX_OBJ_TYPE_VCPU:
      return "vcpu";
    case ZX_OBJ_TYPE_TIMER:
      return "timer";
    case ZX_OBJ_TYPE_IOMMU:
      return "iommu";
    case ZX_OBJ_TYPE_BTI:
      return "bti";
    case ZX_OBJ_TYPE_PROFILE:
      return "profile";
    default:
      return "unknown";
  }
}

zx_status_t GetProcessHandleStats(const zx::process* process,
                                  zx_info_process_handle_stats_t* process_handle_stats) {
  zx_status_t status = process->get_info(ZX_INFO_PROCESS_HANDLE_STATS, process_handle_stats,
                                         sizeof(zx_info_process_handle_stats), nullptr, nullptr);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "zx_object_get_info failed, status: " << status;
    return status;
  }

  return ZX_OK;
}

zx_status_t GetTaskStats(const zx::process* process, zx_info_task_stats_t* task_stats) {
  zx_status_t status = process->get_info(ZX_INFO_TASK_STATS, task_stats,
                                         sizeof(zx_info_task_stats_t), nullptr, nullptr);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "zx_object_get_info failed, status: " << status;
    return status;
  }

  return ZX_OK;
}

zx_status_t GetThreadStats(zx_handle_t thread, zx_info_thread_stats_t* thread_stats) {
  zx_status_t status = zx_object_get_info(thread, ZX_INFO_THREAD_STATS, thread_stats,
                                          sizeof(zx_info_thread_stats_t), nullptr, nullptr);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "zx_object_get_info failed, status: " << status << " thread: " << thread;
    return status;
  }

  return ZX_OK;
}

void GetThreads(const zx::process* process, std::vector<ThreadInfo>* out) {
  zx_koid_t thread_ids[kMaxThreads];
  size_t num_ids;
  if (process->get_info(ZX_INFO_PROCESS_THREADS, thread_ids, sizeof(zx_koid_t) * kMaxThreads,
                        &num_ids, nullptr) != ZX_OK) {
    return;
  }

  for (size_t i = 0; i < num_ids; i++) {
    zx::thread t;
    char name[ZX_MAX_NAME_LEN];
    zx_info_thread_stats_t stats = {};
    if (process->get_child(thread_ids[i], ZX_RIGHT_SAME_RIGHTS, &t) != ZX_OK) {
      return;
    }
    if (t.get_property(ZX_PROP_NAME, &name, ZX_MAX_NAME_LEN) != ZX_OK) {
      return;
    }
    if (GetThreadStats(t.get(), &stats) != ZX_OK) {
      return;
    }
    out->push_back(ThreadInfo{thread_ids[i], name, std::move(t), stats.total_runtime});
  }
}

fit::promise<inspect::Inspector> PopulateThreadInspect(zx::process* process) {
  // Make a 1mb buffer.
  inspect::Inspector inspector(inspect::InspectSettings{.maximum_size = 1024 * 1024});

  std::vector<ThreadInfo> threads;
  threads.reserve(kMaxThreads);
  GetThreads(process, &threads);

  for (const auto& thread : threads) {
    inspect::ValueList values;
    auto koid_string = StringPrintf("%lu", thread.koid);
    auto thread_obj = inspector.GetRoot().CreateChild(koid_string);
    thread_obj.CreateString("name", thread.name.data(), &values);
    thread_obj.CreateInt("total_runtime", thread.runtime, &values);
    auto stack_obj = thread_obj.CreateChild("stack");
    zx_koid_t koids[] = {thread.koid};
    stack_obj.CreateString(
        "dump",
        StringPrintf("\n%s", component::DebugInfoRetriever::GetInfo(process, koids, 1).data()),
        &values);

    values.emplace(std::move(thread_obj));
    values.emplace(std::move(stack_obj));
    inspector.emplace(std::move(values));
  }

  return fit::make_ok_promise(std::move(inspector));
}

fit::promise<inspect::Inspector> PopulateMemoryInspect(zx::process* process) {
  inspect::Inspector inspector;

  zx_info_task_stats_t task_stats = {};
  GetTaskStats(process, &task_stats);
  inspector.GetRoot().CreateUint("mapped_bytes", task_stats.mem_mapped_bytes, &inspector);
  inspector.GetRoot().CreateUint("private_bytes", task_stats.mem_private_bytes, &inspector);
  inspector.GetRoot().CreateUint("shared_bytes", task_stats.mem_shared_bytes, &inspector);
  inspector.GetRoot().CreateUint("scaled_shared_bytes", task_stats.mem_scaled_shared_bytes,
                                 &inspector);

  return fit::make_ok_promise(std::move(inspector));
}
}  // namespace

namespace component {

SystemDiagnosticsDirectory::SystemDiagnosticsDirectory(zx::process process)
    : process_(std::move(process)), inspector_() {
  inspector_.GetRoot().CreateLazyNode(
      "handle_count",
      [this]() -> fit::promise<inspect::Inspector> {
        inspect::Inspector inspector;
        zx_info_process_handle_stats_t process_handle_stats;
        if (GetProcessHandleStats(&process_, &process_handle_stats) != ZX_OK) {
          return fit::make_result_promise<inspect::Inspector>(fit::error());
        }

        for (zx_obj_type_t obj_type = ZX_OBJ_TYPE_NONE; obj_type < ZX_OBJ_TYPE_UPPER_BOUND;
             ++obj_type) {
          inspector.GetRoot().CreateUint(obj_type_get_name(obj_type),
                                         process_handle_stats.handle_count[obj_type], &inspector);
        }
        return fit::make_ok_promise(std::move(inspector));
      },
      &inspector_);
  inspector_.GetRoot().CreateLazyNode(
      "threads", [this] { return PopulateThreadInspect(&process_); }, &inspector_);
  inspector_.GetRoot().CreateLazyNode(
      "memory", [this] { return PopulateMemoryInspect(&process_); }, &inspector_);
}

}  // namespace component
