// 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
