// Copyright 2017 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/cpuperf_provider/app.h"

#include <iostream>
#include <limits>
#include <memory>

#include <lib/async/default.h>

#include <src/lib/fxl/command_line.h>
#include <src/lib/fxl/logging.h>
#include <src/lib/fxl/strings/string_number_conversions.h>

#include "garnet/bin/cpuperf_provider/categories.h"
#include "garnet/bin/cpuperf_provider/importer.h"
#include "garnet/lib/perfmon/controller.h"
#include "garnet/lib/perfmon/reader.h"

namespace cpuperf_provider {

namespace {

// If only fxl string/number conversions supported 0x.

bool ParseNumber(const char* name, const fxl::StringView& arg, uint64_t* value) {
  if (arg.size() > 2 && arg[0] == '0' && (arg[1] == 'x' || arg[1] == 'X')) {
    if (!fxl::StringToNumberWithError<uint64_t>(arg.substr(2), value, fxl::Base::k16)) {
      FXL_LOG(ERROR) << "Invalid value for " << name << ": " << arg;
      return false;
    }
  } else {
    if (!fxl::StringToNumberWithError<uint64_t>(arg, value)) {
      FXL_LOG(ERROR) << "Invalid value for " << name << ": " << arg;
      return false;
    }
  }
  return true;
}

bool GetBufferSizeInPages(uint32_t size_in_mb, uint32_t* out_num_pages) {
  const uint64_t kPagesPerMb = 1024 * 1024 / perfmon::Controller::kPageSize;
  const uint64_t kMaxSizeInMb = std::numeric_limits<uint32_t>::max() / kPagesPerMb;
  if (size_in_mb > kMaxSizeInMb) {
    return false;
  }
  *out_num_pages = size_in_mb * kPagesPerMb;
  return true;
}

}  // namespace

App::App(const fxl::CommandLine& command_line) : startup_context_(sys::ComponentContext::Create()) {
  if (command_line.HasOption("help")) {
    PrintHelp();
    exit(EXIT_SUCCESS);
  }

  std::string buffer_size_as_string;
  if (command_line.GetOptionValue("buffer-size", &buffer_size_as_string)) {
    uint64_t buffer_size;
    if (!ParseNumber("buffer-size", buffer_size_as_string, &buffer_size))
      exit(EXIT_FAILURE);
    if (buffer_size == 0) {
      FXL_LOG(ERROR) << "Buffer size cannot be zero";
      exit(EXIT_FAILURE);
    }
    // The provided buffer size is in MB, the controller takes the buffer size
    // in pages.
    uint32_t buffer_size_in_pages;
    if (!GetBufferSizeInPages(buffer_size, &buffer_size_in_pages)) {
      FXL_LOG(ERROR) << "Buffer size too large";
      exit(EXIT_FAILURE);
    }
    buffer_size_in_pages_ = buffer_size_in_pages;
  }

  // The supported models and their names are determined by lib/perfmon.
  // These are defaults for now.
  model_event_manager_ = perfmon::ModelEventManager::Create(perfmon::GetDefaultModelName());
  FXL_CHECK(model_event_manager_);

  trace_observer_.Start(async_get_default_dispatcher(), [this] { UpdateState(); });
}

App::~App() {}

void App::PrintHelp() {
  std::cout << "cpuperf_provider [options]" << std::endl;
  std::cout << "Options:" << std::endl;
  std::cout << "  --help: Produce this help message" << std::endl;
  std::cout << "  --buffer-size=<size>: Trace data buffer size (MB) [default="
            << kDefaultBufferSizeInMb << "]" << std::endl;
}

void App::UpdateState() {
  if (trace_state() == TRACE_STARTED) {
    FXL_DCHECK(!IsTracing());
    auto new_config = TraceConfig::Create(model_event_manager_.get(), trace_is_category_enabled);
    if (new_config != nullptr && new_config->is_enabled()) {
      StartTracing(std::move(new_config));
    }
  } else {
    StopTracing();
  }
}

void App::StartTracing(std::unique_ptr<TraceConfig> trace_config) {
  FXL_DCHECK(trace_config->is_enabled());
  FXL_DCHECK(!context_);
  FXL_DCHECK(!controller_);

  perfmon::Config device_config;
  if (!trace_config->TranslateToDeviceConfig(&device_config)) {
    FXL_LOG(ERROR) << "Error converting trace config to device config";
    return;
  }

  std::unique_ptr<perfmon::Controller> controller;
  if (!perfmon::Controller::Create(buffer_size_in_pages_, device_config, &controller)) {
    FXL_LOG(ERROR) << "Perfmon controller failed to initialize";
    return;
  }

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

  FXL_VLOG(1) << "Starting trace, config = " << trace_config->ToString();

  start_time_ = zx_ticks_get();
  if (!controller->Start())
    goto Fail;

  FXL_LOG(INFO) << "Started tracing";
  trace_config_ = std::move(trace_config);
  controller_.reset(controller.release());
  return;

Fail:
  trace_release_prolonged_context(context_);
  context_ = nullptr;
}

void App::StopTracing() {
  if (!IsTracing()) {
    return;
  }
  FXL_DCHECK(trace_config_->is_enabled());

  FXL_LOG(INFO) << "Stopping trace";

  controller_->Stop();

  stop_time_ = zx_ticks_get();

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

  auto reader = controller_->GetReader();
  if (reader) {
    Importer importer(buffer_context, trace_config_.get(), start_time_, stop_time_);
    const perfmon::Config& config = controller_->config();
    if (!importer.Import(*reader, config)) {
      FXL_LOG(ERROR) << "Errors encountered while importing perfmon data";
    }
  } else {
    FXL_LOG(ERROR) << "Unable to initialize reader";
  }

  trace_release_context(buffer_context);
  trace_release_prolonged_context(context_);
  context_ = nullptr;
  trace_config_.reset();
  controller_.reset();
}

}  // namespace cpuperf_provider
