// 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 "provider_impl.h"

#include <fidl/fuchsia.tracing.provider/cpp/wire.h>
#include <fidl/fuchsia.tracing/cpp/wire.h>
#include <lib/async/cpp/task.h>
#include <lib/zx/process.h>
#include <stdio.h>
#include <zircon/assert.h>
#include <zircon/status.h>

#include <utility>

#include "export.h"
#include "lib/trace-engine/handler.h"
#include "lib/trace-engine/types.h"
#include "lib/trace-provider/provider.h"
#include "session.h"
#include "utils.h"

namespace {
trace_buffering_mode_t FidlBufferingModeToTraceEngineBufferingMode(
    fuchsia_tracing::wire::BufferingMode buffering_mode) {
  switch (buffering_mode) {
    case fuchsia_tracing::wire::BufferingMode::kOneshot:
      return TRACE_BUFFERING_MODE_ONESHOT;
    case fuchsia_tracing::wire::BufferingMode::kCircular:
      return TRACE_BUFFERING_MODE_CIRCULAR;
    case fuchsia_tracing::wire::BufferingMode::kStreaming:
      return TRACE_BUFFERING_MODE_STREAMING;
  }
}

trace_start_mode_t FidlBufferingDispositionToTraceEngineStartMode(
    fuchsia_tracing::BufferDisposition buffer_disposition) {
  switch (buffer_disposition) {
    case fuchsia_tracing::wire::BufferDisposition::kClearEntire:
      return TRACE_START_CLEAR_ENTIRE_BUFFER;
    case fuchsia_tracing::wire::BufferDisposition::kClearNondurable:
      return TRACE_START_CLEAR_NONDURABLE_BUFFER;
    case fuchsia_tracing::wire::BufferDisposition::kRetain:
      return TRACE_START_RETAIN_BUFFER;
  }
}

std::vector<std::string> CloneCategories(
    const fuchsia_tracing_provider::wire::ProviderConfig& config) {
  std::vector<std::string> categories;
  categories.reserve(config.categories.count());
  for (const auto& category : config.categories) {
    categories.emplace_back(category.data(), category.size());
  }
  return categories;
}
}  // namespace

namespace trace {
namespace internal {

constexpr bool kVerboseTraceErrors = false;

TraceProviderImpl::TraceProviderImpl(std::string name, async_dispatcher_t* dispatcher,
                                     fidl::ServerEnd<fuchsia_tracing_provider::Provider> server_end)
    : name_(std::move(name)), dispatcher_(dispatcher), executor_(dispatcher) {
  fidl::BindServer(
      dispatcher_, std::move(server_end), this,
      [](TraceProviderImpl* impl, fidl::UnbindInfo info,
         fidl::ServerEnd<fuchsia_tracing_provider::Provider> server_end) { OnClose(); });
}

void TraceProviderImpl::Initialize(
    fuchsia_tracing_provider::wire::ProviderInitializeRequest* request,
    InitializeCompleter::Sync& completer) {
  fuchsia_tracing_provider::wire::ProviderConfig& config = request->config;
  Session::InitializeEngine(
      dispatcher_, FidlBufferingModeToTraceEngineBufferingMode(config.buffering_mode),
      std::move(config.buffer), std::move(config.fifo), CloneCategories(config));
  provider_config_ = {
      .buffering_mode = FidlBufferingModeToTraceEngineBufferingMode(config.buffering_mode),
      .categories = CloneCategories(config),
  };
}

void TraceProviderImpl::Start(fuchsia_tracing_provider::wire::ProviderStartRequest* request,
                              StartCompleter::Sync& completer) {
  const fuchsia_tracing_provider::wire::StartOptions& options = request->options;
  // TODO(https://fxbug.dev/42097006): Add support for additional categories.
  Session::StartEngine(FidlBufferingDispositionToTraceEngineStartMode(options.buffer_disposition));
}

void TraceProviderImpl::Stop(StopCompleter::Sync& completer) { Session::StopEngine(); }

void TraceProviderImpl::Terminate(TerminateCompleter::Sync& completer) { OnClose(); }

void TraceProviderImpl::GetKnownCategories(GetKnownCategoriesCompleter::Sync& completer) {
  if (get_known_categories_callback_ != nullptr) {
    auto promise = get_known_categories_callback_().then(
        [completer = completer.ToAsync(),
         name = name_](fpromise::result<std::vector<trace::KnownCategory>>& result) mutable {
          if (result.is_error()) {
            fprintf(stderr, "TraceProvider: error getting known categories for %s\n", name.c_str());
            completer.Reply({});
            return;
          }
          auto known_categories = result.take_value();
          std::vector<fuchsia_tracing::wire::KnownCategory> known_categories_fidl;
          known_categories_fidl.reserve(known_categories.size());
          for (const auto& known_category : known_categories) {
            known_categories_fidl.push_back(fuchsia_tracing::wire::KnownCategory{
                fidl::StringView::FromExternal(known_category.name),
                fidl::StringView::FromExternal(known_category.description)});
          }
          completer.Reply(fidl::VectorView<fuchsia_tracing::wire::KnownCategory>::FromExternal(
              known_categories_fidl));
        });
    executor_.schedule_task(std::move(promise));
    return;
  }

  // TODO(https://fxbug.dev/42068744): Return the trace categories that were registered with the category string
  // literal.
  completer.Reply({});
}

void TraceProviderImpl::SetGetKnownCategoriesCallback(GetKnownCategoriesCallback callback) {
  get_known_categories_callback_ = std::move(callback);
}

void TraceProviderImpl::OnClose() { Session::TerminateEngine(); }

const ProviderConfig& TraceProviderImpl::GetProviderConfig() const { return provider_config_; }

}  // namespace internal

ProviderConfig TraceProvider::GetProviderConfig() const {
  ZX_DEBUG_ASSERT(provider_);
  const auto* provider_impl = reinterpret_cast<internal::TraceProviderImpl*>(provider_);
  return provider_impl->GetProviderConfig();
}

void TraceProvider::SetGetKnownCategoriesCallback(GetKnownCategoriesCallback callback) {
  ZX_DEBUG_ASSERT(provider_);
  auto* provider_impl = reinterpret_cast<internal::TraceProviderImpl*>(provider_);
  provider_impl->SetGetKnownCategoriesCallback(std::move(callback));
}
}  // namespace trace

EXPORT trace_provider_t* trace_provider_create_with_name(zx_handle_t to_service_h,
                                                         async_dispatcher_t* dispatcher,
                                                         const char* name) {
  const fidl::ClientEnd<fuchsia_tracing_provider::Registry> to_service{zx::channel{to_service_h}};

  ZX_DEBUG_ASSERT(to_service.is_valid());
  ZX_DEBUG_ASSERT(dispatcher);

  // Create the channel to which we will bind the trace provider.
  zx::result endpoints = fidl::CreateEndpoints<fuchsia_tracing_provider::Provider>();
  if (endpoints.is_error()) {
    fprintf(stderr, "TraceProvider: channel create failed: status=%d(%s)\n",
            endpoints.status_value(), endpoints.status_string());
    return nullptr;
  }

  // Register the trace provider.
  const fidl::Status result =
      fidl::WireCall(to_service)
          ->RegisterProvider(std::move(endpoints->client), trace::internal::GetPid(),
                             fidl::StringView::FromExternal(name));
  if (!result.ok()) {
    if (trace::internal::kVerboseTraceErrors) {
      fprintf(stderr, "TraceProvider: registry failed: result=%s\n",
              result.FormatDescription().c_str());
    }
    return nullptr;
  }
  // Note: |to_service| can be closed now. Let it close as a consequence
  // of going out of scope.

  return new trace::internal::TraceProviderImpl(name, dispatcher, std::move(endpoints->server));
}

EXPORT trace_provider_t* trace_provider_create(zx_handle_t to_service,
                                               async_dispatcher_t* dispatcher) {
  auto self = zx::process::self();
  char name[ZX_MAX_NAME_LEN];
  auto status = self->get_property(ZX_PROP_NAME, name, sizeof(name));
  if (status != ZX_OK) {
    fprintf(stderr, "TraceProvider: error getting process name: status=%d(%s)\n", status,
            zx_status_get_string(status));
    name[0] = '\0';
  }
  return trace_provider_create_with_name(to_service, dispatcher, name);
}

EXPORT trace_provider_t* trace_provider_create_synchronously(zx_handle_t to_service_h,
                                                             async_dispatcher_t* dispatcher,
                                                             const char* name,
                                                             bool* out_already_started) {
  const fidl::ClientEnd<fuchsia_tracing_provider::Registry> to_service{zx::channel{to_service_h}};

  ZX_DEBUG_ASSERT(to_service.is_valid());
  ZX_DEBUG_ASSERT(dispatcher);

  // Create the channel to which we will bind the trace provider.
  zx::result endpoints = fidl::CreateEndpoints<fuchsia_tracing_provider::Provider>();
  if (endpoints.is_error()) {
    fprintf(stderr, "TraceProvider: channel create failed: status=%d(%s)\n",
            endpoints.status_value(), endpoints.status_string());
    return nullptr;
  }

  // Register the trace provider.
  const fidl::WireResult result =
      fidl::WireCall(to_service)
          ->RegisterProviderSynchronously(std::move(endpoints->client), trace::internal::GetPid(),
                                          fidl::StringView::FromExternal(name));
  if (!result.ok()) {
    fprintf(stderr, "TraceProvider: RegisterProviderSynchronously failed: result=%s\n",
            result.FormatDescription().c_str());
    return nullptr;
  }
  const fidl::WireResponse response = result.value();
  if (const zx_status_t status = response.s; status != ZX_OK) {
    fprintf(stderr, "TraceProvider: registry failed: status=%d(%s)\n", status,
            zx_status_get_string(status));
    return nullptr;
  }
  // Note: |to_service| can be closed now. Let it close as a consequence
  // of going out of scope.

  if (out_already_started) {
    *out_already_started = response.started;
  }
  return new trace::internal::TraceProviderImpl(name, dispatcher, std::move(endpoints->server));
}

EXPORT void trace_provider_destroy(trace_provider_t* provider) {
  ZX_DEBUG_ASSERT(provider);

  // The provider's dispatcher may be running on a different thread. This happens when, e.g., the
  // dispatcher is running in a background thread and we are called in the foreground thread.
  // async::WaitBase, which we use, requires all calls be made on the dispatcher thread. Thus we
  // can't delete |provider| here. Instead we schedule it to be deleted on the dispatcher's thread.
  //
  // There are two cases to be handled:
  // 1) The dispatcher's thread is our thread.
  // 2) The dispatcher's thread is a different thread.
  // In both cases there's an additional wrinkle:
  // a) The task we post is run.
  // b) The task we post is not run.
  // In cases (1a,2a) we're ok: The provider is deleted. The provider isn't destroyed immediately
  // but that's ok, it will be shortly.
  // In cases (1b,2b) we're also ok. The only time this happens is if the loop is shutdown before
  // our task is run. This is ok because when this happens our WaitBase method cannot be running.
  //
  // While one might want to check whether we're running in a different thread from the dispatcher
  // with dispatcher == async_get_default_dispatcher(), we don't do this as we don't assume the
  // default dispatcher has been set.

  auto raw_provider_impl = static_cast<trace::internal::TraceProviderImpl*>(provider);
  std::unique_ptr<trace::internal::TraceProviderImpl> provider_impl(raw_provider_impl);
  async::PostTask(raw_provider_impl->dispatcher(), [provider_impl = std::move(provider_impl)]() {
    // The provider will be deleted when the closure is deleted.
  });
}
