/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/traced/probes/ftrace/ftrace_data_source.h"

#include "perfetto/ext/base/string_splitter.h"
#include "perfetto/ext/base/string_utils.h"
#include "perfetto/ext/base/string_view.h"
#include "perfetto/ext/base/subprocess.h"
#include "perfetto/protozero/scattered_heap_buffer.h"
#include "perfetto/tracing/core/data_source_descriptor.h"
#include "src/traced/probes/ftrace/cpu_reader.h"
#include "src/traced/probes/ftrace/ftrace_controller.h"

#include "protos/perfetto/common/ftrace_descriptor.pbzero.h"
#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
#include "protos/perfetto/trace/ftrace/ftrace_stats.pbzero.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"

namespace perfetto {
namespace {

void FillFtraceDataSourceDescriptor(DataSourceDescriptor* dsd) {
  protozero::HeapBuffered<protos::pbzero::FtraceDescriptor> ftd;

#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
  base::Subprocess p({"/system/bin/atrace", "--list_categories"});
  p.args.stdin_mode = base::Subprocess::InputMode::kDevNull;
  p.args.stdout_mode = base::Subprocess::OutputMode::kBuffer;
  p.args.stderr_mode = base::Subprocess::OutputMode::kBuffer;
  bool res = p.Call(/*timeout_ms=*/20000);
  if (res) {
    for (base::StringSplitter ss(std::move(p.output()), '\n'); ss.Next();) {
      base::StringView line(ss.cur_token(), ss.cur_token_size());
      size_t pos = line.find(" - ");
      if (pos == line.npos) {
        continue;
      }
      base::StringView name = line.substr(0, pos);
      // Trim initial whitespaces
      auto it = std::find_if(name.begin(), name.end(),
                             [](char c) { return c != ' '; });
      name = name.substr(static_cast<size_t>(it - name.begin()));

      base::StringView desc = line.substr(pos + 3);

      protos::pbzero::FtraceDescriptor::AtraceCategory* cat =
          ftd->add_atrace_categories();
      cat->set_name(name.data(), name.size());
      cat->set_description(desc.data(), desc.size());
    }
  } else {
    PERFETTO_ELOG("Failed to run atrace --list_categories code(%d): %s",
                  p.returncode(), p.output().c_str());
  }
#endif

  dsd->set_ftrace_descriptor_raw(ftd.SerializeAsString());
}

}  // namespace

// static
const ProbesDataSource::Descriptor FtraceDataSource::descriptor = {
    /*name*/ "linux.ftrace",
    /*flags*/ Descriptor::kFlagsNone,
    /*fill_descriptor_func*/ &FillFtraceDataSourceDescriptor,
};

FtraceDataSource::FtraceDataSource(
    base::WeakPtr<FtraceController> controller_weak,
    TracingSessionID session_id,
    const FtraceConfig& config,
    std::unique_ptr<TraceWriter> writer)
    : ProbesDataSource(session_id, &descriptor),
      config_(config),
      writer_(std::move(writer)),
      controller_weak_(std::move(controller_weak)) {}

FtraceDataSource::~FtraceDataSource() {
  if (controller_weak_)
    controller_weak_->RemoveDataSource(this);
}

void FtraceDataSource::Initialize(
    FtraceConfigId config_id,
    const FtraceDataSourceConfig* parsing_config) {
  PERFETTO_CHECK(config_id);
  config_id_ = config_id;
  parsing_config_ = parsing_config;
}

void FtraceDataSource::Start() {
  FtraceController* ftrace = controller_weak_.get();
  if (!ftrace)
    return;
  PERFETTO_CHECK(config_id_);  // Must be initialized at this point.
  if (!ftrace->StartDataSource(this))
    return;
  DumpFtraceStats(&stats_before_);
  setup_errors_ = FtraceSetupErrors();  // Dump only on START_OF_TRACE.

  if (config_.preserve_ftrace_buffer()) {
    auto stats_packet = writer_->NewTracePacket();
    auto* stats = stats_packet->set_ftrace_stats();
    stats->set_phase(protos::pbzero::FtraceStats::Phase::START_OF_TRACE);
    stats->set_preserve_ftrace_buffer(true);
  }
}

void FtraceDataSource::DumpFtraceStats(FtraceStats* stats) {
  if (controller_weak_)
    controller_weak_->DumpFtraceStats(this, stats);
  stats->setup_errors = std::move(setup_errors_);
}

void FtraceDataSource::Flush(FlushRequestID flush_request_id,
                             std::function<void()> callback) {
  if (!controller_weak_)
    return;

  pending_flushes_[flush_request_id] = std::move(callback);

  // FtraceController will call OnFtraceFlushComplete() once the data has been
  // drained from the ftrace buffer and written into the various writers of
  // all its active data sources.
  controller_weak_->Flush(flush_request_id);
}

// Called by FtraceController after all CPUs have acked the flush or timed out.
void FtraceDataSource::OnFtraceFlushComplete(FlushRequestID flush_request_id) {
  auto it = pending_flushes_.find(flush_request_id);
  if (it == pending_flushes_.end()) {
    // This can genuinely happen in case of concurrent ftrace sessions. When a
    // FtraceDataSource issues a flush, the controller has to drain ftrace data
    // for everybody (there is only one kernel ftrace buffer for all sessions).
    // FtraceController doesn't bother to remember which FtraceDataSource did or
    // did not request a flush. Instead just boradcasts the
    // OnFtraceFlushComplete() to all of them.
    return;
  }
  auto callback = std::move(it->second);
  pending_flushes_.erase(it);
  if (writer_) {
    WriteStats();
    writer_->Flush(std::move(callback));
  }
}

void FtraceDataSource::WriteStats() {
  {
    auto before_packet = writer_->NewTracePacket();
    auto out = before_packet->set_ftrace_stats();
    out->set_phase(protos::pbzero::FtraceStats::Phase::START_OF_TRACE);
    stats_before_.Write(out);
  }
  {
    FtraceStats stats_after{};
    DumpFtraceStats(&stats_after);
    auto after_packet = writer_->NewTracePacket();
    auto out = after_packet->set_ftrace_stats();
    out->set_phase(protos::pbzero::FtraceStats::Phase::END_OF_TRACE);
    stats_after.Write(out);
  }
}

}  // namespace perfetto
