/*
 * 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 "perfetto/public/consumer_api.h"

#include <fcntl.h>
#include <inttypes.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <unistd.h>

#include <atomic>
#include <condition_variable>
#include <memory>
#include <mutex>
#include <thread>

#include "perfetto/base/build_config.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/temp_file.h"
#include "perfetto/ext/base/thread_checker.h"
#include "perfetto/ext/base/unix_task_runner.h"
#include "perfetto/ext/base/utils.h"
#include "perfetto/ext/tracing/core/consumer.h"
#include "perfetto/ext/tracing/core/trace_packet.h"
#include "perfetto/ext/tracing/ipc/consumer_ipc_client.h"
#include "perfetto/ext/tracing/ipc/default_socket.h"
#include "perfetto/tracing/core/trace_config.h"

#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
#include <linux/memfd.h>
#include <sys/syscall.h>
#endif

#include "protos/perfetto/config/trace_config.pb.h"

#define PERFETTO_EXPORTED_API __attribute__((visibility("default")))

namespace perfetto {
namespace consumer {

namespace {

class TracingSession : public Consumer {
 public:
  TracingSession(base::TaskRunner*,
                 Handle,
                 OnStateChangedCb,
                 void* callback_arg,
                 const perfetto::protos::TraceConfig&);
  ~TracingSession() override;

  // Note: if making this class moveable, the move-ctor/dtor must be updated
  // to clear up mapped_buf_ on dtor.

  // These methods are called on a thread != |task_runner_|.
  State state() const { return state_; }
  std::pair<char*, size_t> mapped_buf() const {
    // The comparison operator will do an acquire-load on the atomic |state_|.
    if (state_ == State::kTraceEnded)
      return std::make_pair(mapped_buf_, mapped_buf_size_);
    return std::make_pair(nullptr, 0);
  }

  // All the methods below are called only on the |task_runner_| thread.

  bool Initialize();
  void StartTracing();

  // perfetto::Consumer implementation.
  void OnConnect() override;
  void OnDisconnect() override;
  void OnTracingDisabled() override;
  void OnTraceData(std::vector<TracePacket>, bool has_more) override;
  void OnDetach(bool) override;
  void OnAttach(bool, const TraceConfig&) override;
  void OnTraceStats(bool, const TraceStats&) override;
  void OnObservableEvents(const ObservableEvents&) override;

 private:
  TracingSession(const TracingSession&) = delete;
  TracingSession& operator=(const TracingSession&) = delete;

  void DestroyConnection();
  void NotifyCallback();

  base::TaskRunner* const task_runner_;
  Handle const handle_;
  OnStateChangedCb const callback_ = nullptr;
  void* const callback_arg_ = nullptr;
  TraceConfig trace_config_;
  base::ScopedFile buf_fd_;
  std::unique_ptr<TracingService::ConsumerEndpoint> consumer_endpoint_;

  // |mapped_buf_| and |mapped_buf_size_| are seq-consistent with |state_|.
  std::atomic<State> state_{State::kIdle};
  char* mapped_buf_ = nullptr;
  size_t mapped_buf_size_ = 0;

  PERFETTO_THREAD_CHECKER(thread_checker_)
};

TracingSession::TracingSession(
    base::TaskRunner* task_runner,
    Handle handle,
    OnStateChangedCb callback,
    void* callback_arg,
    const perfetto::protos::TraceConfig& trace_config_proto)
    : task_runner_(task_runner),
      handle_(handle),
      callback_(callback),
      callback_arg_(callback_arg) {
  PERFETTO_DETACH_FROM_THREAD(thread_checker_);
  trace_config_.FromProto(trace_config_proto);
  trace_config_.set_write_into_file(true);

  // TODO(primiano): this really doesn't matter because the trace will be
  // flushed into the file when stopping. We need a way to be able to say
  // "disable periodic flushing and flush only when stopping".
  trace_config_.set_file_write_period_ms(60000);
}

TracingSession::~TracingSession() {
  PERFETTO_DCHECK_THREAD(thread_checker_);
  if (mapped_buf_)
    PERFETTO_CHECK(munmap(mapped_buf_, mapped_buf_size_) == 0);
}

bool TracingSession::Initialize() {
  PERFETTO_DCHECK_THREAD(thread_checker_);

  if (state_ != State::kIdle)
    return false;

#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
  char memfd_name[64];
  snprintf(memfd_name, sizeof(memfd_name), "perfetto_trace_%" PRId64, handle_);
  buf_fd_.reset(
      static_cast<int>(syscall(__NR_memfd_create, memfd_name, MFD_CLOEXEC)));
#else
  // Fallback for testing on Linux/mac.
  buf_fd_ = base::TempFile::CreateUnlinked().ReleaseFD();
#endif

  if (!buf_fd_) {
    PERFETTO_PLOG("Failed to allocate temporary tracing buffer");
    return false;
  }

  state_ = State::kConnecting;
  consumer_endpoint_ =
      ConsumerIPCClient::Connect(GetConsumerSocket(), this, task_runner_);

  return true;
}

// Called after EnabledTracing, soon after the IPC connection is established.
void TracingSession::OnConnect() {
  PERFETTO_DCHECK_THREAD(thread_checker_);

  PERFETTO_DLOG("OnConnect");
  PERFETTO_DCHECK(state_ == State::kConnecting);
  consumer_endpoint_->EnableTracing(trace_config_,
                                    base::ScopedFile(dup(*buf_fd_)));
  if (trace_config_.deferred_start())
    state_ = State::kConfigured;
  else
    state_ = State::kTracing;
  NotifyCallback();
}

void TracingSession::StartTracing() {
  PERFETTO_DCHECK_THREAD(thread_checker_);

  auto state = state_.load();
  if (state != State::kConfigured) {
    PERFETTO_ELOG("StartTracing(): invalid state (%d)",
                  static_cast<int>(state));
    return;
  }
  state_ = State::kTracing;
  consumer_endpoint_->StartTracing();
}

void TracingSession::OnTracingDisabled() {
  PERFETTO_DCHECK_THREAD(thread_checker_);
  PERFETTO_DLOG("OnTracingDisabled");

  struct stat stat_buf {};
  int res = fstat(buf_fd_.get(), &stat_buf);
  mapped_buf_size_ = res == 0 ? static_cast<size_t>(stat_buf.st_size) : 0;
  mapped_buf_ =
      static_cast<char*>(mmap(nullptr, mapped_buf_size_, PROT_READ | PROT_WRITE,
                              MAP_SHARED, buf_fd_.get(), 0));
  DestroyConnection();
  if (mapped_buf_size_ == 0 || mapped_buf_ == MAP_FAILED) {
    mapped_buf_ = nullptr;
    mapped_buf_size_ = 0;
    state_ = State::kTraceFailed;
    PERFETTO_ELOG("Tracing session failed");
  } else {
    state_ = State::kTraceEnded;
  }
  NotifyCallback();
}

void TracingSession::OnDisconnect() {
  PERFETTO_DCHECK_THREAD(thread_checker_);
  PERFETTO_DLOG("OnDisconnect");
  DestroyConnection();
  state_ = State::kConnectionError;
  NotifyCallback();
}

void TracingSession::OnDetach(bool) {
  PERFETTO_DCHECK(false);  // Should never be called, Detach() is not used here.
}

void TracingSession::OnAttach(bool, const TraceConfig&) {
  PERFETTO_DCHECK(false);  // Should never be called, Attach() is not used here.
}

void TracingSession::OnTraceStats(bool, const TraceStats&) {
  // Should never be called, GetTraceStats() is not used here.
  PERFETTO_DCHECK(false);
}

void TracingSession::OnObservableEvents(const ObservableEvents&) {
  // Should never be called, ObserveEvents() is not used here.
  PERFETTO_DCHECK(false);
}

void TracingSession::DestroyConnection() {
  // Destroys the connection in a separate task. This is to avoid destroying
  // the IPC connection directly from within the IPC callback.
  TracingService::ConsumerEndpoint* endpoint = consumer_endpoint_.release();
  task_runner_->PostTask([endpoint] { delete endpoint; });
}

void TracingSession::OnTraceData(std::vector<TracePacket>, bool) {
  // This should be never called because we are using |write_into_file| and
  // asking the traced service to directly write into the |buf_fd_|.
  PERFETTO_DFATAL("Should be unreachable.");
}

void TracingSession::NotifyCallback() {
  if (!callback_)
    return;
  auto state = state_.load();
  auto callback = callback_;
  auto handle = handle_;
  auto callback_arg = callback_arg_;
  task_runner_->PostTask([callback, callback_arg, handle, state] {
    callback(handle, state, callback_arg);
  });
}

class TracingController {
 public:
  static TracingController* GetInstance();
  TracingController();

  // These methods are called from a thread != |task_runner_|.
  Handle Create(const void*, size_t, OnStateChangedCb, void* callback_arg);
  void StartTracing(Handle);
  State PollState(Handle);
  TraceBuffer ReadTrace(Handle);
  void Destroy(Handle);

 private:
  void ThreadMain();  // Called on |task_runner_| thread.

  std::mutex mutex_;
  std::thread thread_;
  std::unique_ptr<base::UnixTaskRunner> task_runner_;
  std::condition_variable task_runner_initialized_;
  Handle last_handle_ = 0;
  std::map<Handle, std::unique_ptr<TracingSession>> sessions_;
};

TracingController* TracingController::GetInstance() {
  static TracingController* instance = new TracingController();
  return instance;
}

TracingController::TracingController()
    : thread_(&TracingController::ThreadMain, this) {
  std::unique_lock<std::mutex> lock(mutex_);
  task_runner_initialized_.wait(lock, [this] { return !!task_runner_; });
}

void TracingController::ThreadMain() {
  {
    std::unique_lock<std::mutex> lock(mutex_);
    task_runner_.reset(new base::UnixTaskRunner());
  }
  task_runner_initialized_.notify_one();
  task_runner_->Run();
}

Handle TracingController::Create(const void* config_proto_buf,
                                 size_t config_len,
                                 OnStateChangedCb callback,
                                 void* callback_arg) {
  perfetto::protos::TraceConfig config_proto;
  bool parsed = config_proto.ParseFromArray(config_proto_buf,
                                            static_cast<int>(config_len));
  if (!parsed) {
    PERFETTO_ELOG("Failed to decode TraceConfig proto");
    return kInvalidHandle;
  }

  if (!config_proto.duration_ms()) {
    PERFETTO_ELOG("The trace config must specify a duration");
    return kInvalidHandle;
  }

  std::unique_lock<std::mutex> lock(mutex_);
  Handle handle = ++last_handle_;
  auto* session = new TracingSession(task_runner_.get(), handle, callback,
                                     callback_arg, config_proto);
  sessions_.emplace(handle, std::unique_ptr<TracingSession>(session));

  // Enable the TracingSession on its own thread.
  task_runner_->PostTask([session] { session->Initialize(); });

  return handle;
}

void TracingController::StartTracing(Handle handle) {
  std::unique_lock<std::mutex> lock(mutex_);
  auto it = sessions_.find(handle);
  if (it == sessions_.end()) {
    PERFETTO_ELOG("StartTracing(): Invalid tracing session handle");
    return;
  }
  TracingSession* session = it->second.get();
  task_runner_->PostTask([session] { session->StartTracing(); });
}

State TracingController::PollState(Handle handle) {
  std::unique_lock<std::mutex> lock(mutex_);
  auto it = sessions_.find(handle);
  if (it == sessions_.end())
    return State::kSessionNotFound;
  return it->second->state();
}

TraceBuffer TracingController::ReadTrace(Handle handle) {
  TraceBuffer buf{};

  std::unique_lock<std::mutex> lock(mutex_);
  auto it = sessions_.find(handle);
  if (it == sessions_.end()) {
    PERFETTO_DLOG("Handle invalid");
    return buf;
  }

  TracingSession* session = it->second.get();
  auto state = session->state();
  if (state == State::kTraceEnded) {
    std::tie(buf.begin, buf.size) = session->mapped_buf();
    return buf;
  }

  PERFETTO_DLOG("ReadTrace(): called in an unexpected state (%d)",
                static_cast<int>(state));
  return buf;
}

void TracingController::Destroy(Handle handle) {
  // Post an empty task on the task runner to delete the session on its own
  // thread.
  std::unique_lock<std::mutex> lock(mutex_);
  auto it = sessions_.find(handle);
  if (it == sessions_.end())
    return;
  TracingSession* session = it->second.release();
  sessions_.erase(it);
  task_runner_->PostTask([session] { delete session; });
}

}  // namespace

PERFETTO_EXPORTED_API Handle Create(const void* config_proto,
                                    size_t config_len,
                                    OnStateChangedCb callback,
                                    void* callback_arg) {
  return TracingController::GetInstance()->Create(config_proto, config_len,
                                                  callback, callback_arg);
}

PERFETTO_EXPORTED_API
void StartTracing(Handle handle) {
  return TracingController::GetInstance()->StartTracing(handle);
}

PERFETTO_EXPORTED_API State PollState(Handle handle) {
  return TracingController::GetInstance()->PollState(handle);
}

PERFETTO_EXPORTED_API TraceBuffer ReadTrace(Handle handle) {
  return TracingController::GetInstance()->ReadTrace(handle);
}

PERFETTO_EXPORTED_API void Destroy(Handle handle) {
  TracingController::GetInstance()->Destroy(handle);
}
}  // namespace consumer
}  // namespace perfetto
