// Copyright 2016 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 "garnet/bin/ktrace_provider/app.h"

#include <fcntl.h>
#include <fuchsia/tracing/kernel/c/fidl.h>
#include <lib/async/default.h>
#include <lib/fdio/fdio.h>
#include <lib/zx/channel.h>
#include <trace-engine/instrumentation.h>
#include <trace-provider/provider.h>
#include <unistd.h>
#include <zircon/device/ktrace.h>
#include <zircon/status.h>
#include <zircon/syscalls/log.h>

#include "garnet/bin/ktrace_provider/importer.h"
#include "garnet/bin/ktrace_provider/reader.h"
#include "src/lib/fxl/arraysize.h"
#include "src/lib/fxl/logging.h"

namespace ktrace_provider {
namespace {

constexpr char kKTraceDev[] = "/dev/misc/ktrace";

struct KTraceCategory {
  const char* name;
  uint32_t group;
};

constexpr KTraceCategory kGroupCategories[] = {
    {"kernel", KTRACE_GRP_ALL},
    {"kernel:meta", KTRACE_GRP_META},
    {"kernel:lifecycle", KTRACE_GRP_LIFECYCLE},
    {"kernel:sched", KTRACE_GRP_SCHEDULER},
    {"kernel:tasks", KTRACE_GRP_TASKS},
    {"kernel:ipc", KTRACE_GRP_IPC},
    {"kernel:irq", KTRACE_GRP_IRQ},
    {"kernel:probe", KTRACE_GRP_PROBE},
    {"kernel:arch", KTRACE_GRP_ARCH},
};

// Meta category to retain current contents of ktrace buffer.
constexpr char kRetainCategory[] = "kernel:retain";

constexpr char kLogCategory[] = "log";

zx::channel OpenKTrace() {
  int fd = open(kKTraceDev, O_WRONLY);
  if (fd < 0) {
    FXL_LOG(ERROR) << "Failed to open " << kKTraceDev << ": errno=" << errno;
    return zx::channel();
  }
  zx::channel channel;
  zx_status_t status =
      fdio_get_service_handle(fd, channel.reset_and_get_address());
  if (status != ZX_OK) {
    FXL_LOG(ERROR) << "Failed to get " << kKTraceDev
                   << " channel: " << zx_status_get_string(status);
    return zx::channel();
  }
  return channel;
}

void LogFidlFailure(const char* rqst_name, zx_status_t fidl_status,
                    zx_status_t rqst_status) {
  if (fidl_status != ZX_OK) {
    FXL_LOG(ERROR) << "Ktrace FIDL " << rqst_name
                   << " failed: status=" << fidl_status;
  } else if (rqst_status != ZX_OK) {
    FXL_LOG(ERROR) << "Ktrace " << rqst_name
                   << " failed: status=" << rqst_status;
  }
}

void RequestKtraceStop(const zx::channel& channel) {
  zx_status_t stop_status;
  zx_status_t status =
      fuchsia_tracing_kernel_ControllerStop(channel.get(), &stop_status);
  LogFidlFailure("stop", status, stop_status);
}

void RequestKtraceRewind(const zx::channel& channel) {
  zx_status_t rewind_status;
  zx_status_t status =
      fuchsia_tracing_kernel_ControllerRewind(channel.get(), &rewind_status);
  LogFidlFailure("rewind", status, rewind_status);
}

void RequestKtraceStart(const zx::channel& channel, uint32_t group_mask) {
  zx_status_t start_status;
  zx_status_t status = fuchsia_tracing_kernel_ControllerStart(
      channel.get(), group_mask, &start_status);
  LogFidlFailure("start", status, start_status);
}

}  // namespace

App::App(const fxl::CommandLine& command_line)
    : component_context_(sys::ComponentContext::Create()) {
  trace_observer_.Start(async_get_default_dispatcher(),
                        [this] { UpdateState(); });
}

App::~App() {}

void App::UpdateState() {
  uint32_t group_mask = 0;
  bool capture_log = false;
  bool retain_current_data = false;
  if (trace_state() == TRACE_STARTED) {
    size_t num_enabled_categories = 0;
    for (size_t i = 0; i < arraysize(kGroupCategories); i++) {
      auto& category = kGroupCategories[i];
      if (trace_is_category_enabled(category.name)) {
        group_mask |= category.group;
        ++num_enabled_categories;
      }
    }

    // Avoid capturing log traces in the default case by detecting whether all
    // categories are enabled or not.
    capture_log = trace_is_category_enabled(kLogCategory) &&
                  num_enabled_categories != arraysize(kGroupCategories);

    // The default case is everything is enabled, but |kRetainCategory| must be
    // explicitly passed.
    retain_current_data = trace_is_category_enabled(kRetainCategory) &&
                          num_enabled_categories != arraysize(kGroupCategories);
  }

  if (current_group_mask_ != group_mask) {
    StopKTrace();
    StartKTrace(group_mask, retain_current_data);
  }

  if (capture_log) {
    log_importer_.Start();
  } else {
    log_importer_.Stop();
  }
}

void App::StartKTrace(uint32_t group_mask, bool retain_current_data) {
  FXL_DCHECK(!context_);
  if (!group_mask) {
    return;  // nothing to trace
  }

  FXL_LOG(INFO) << "Starting ktrace";

  zx::channel channel = OpenKTrace();
  if (!channel) {
    return;
  }

  context_ = trace_acquire_prolonged_context();
  if (!context_) {
    // Tracing was disabled in the meantime.
    return;
  }
  current_group_mask_ = group_mask;

  RequestKtraceStop(channel);
  if (!retain_current_data) {
    RequestKtraceRewind(channel);
  }
  RequestKtraceStart(channel, group_mask);

  FXL_VLOG(1) << "Ktrace started";
}

void App::StopKTrace() {
  if (!context_) {
    return;  // not currently tracing
  }
  FXL_DCHECK(current_group_mask_);

  FXL_LOG(INFO) << "Stopping ktrace";

  {
    zx::channel channel = OpenKTrace();
    if (channel) {
      RequestKtraceStop(channel);
    }
  }

  // Acquire a context for writing to the trace buffer.
  auto buffer_context = trace_acquire_context();

  Reader reader;
  Importer importer(buffer_context);
  if (!importer.Import(reader)) {
    FXL_LOG(ERROR) << "Errors encountered while importing ktrace data";
  }

  trace_release_context(buffer_context);
  trace_release_prolonged_context(context_);
  context_ = nullptr;
  current_group_mask_ = 0u;

  FXL_VLOG(1) << "Ktrace stopped";
}

}  // namespace ktrace_provider
