/*
 * Copyright (C) 2017 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 <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include "perfetto/base/logging.h"
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/getopt.h"
#include "perfetto/ext/base/unix_task_runner.h"
#include "perfetto/ext/base/utils.h"
#include "perfetto/ext/base/version.h"
#include "perfetto/ext/traced/traced.h"
#include "perfetto/tracing/default_socket.h"

#include "src/traced/probes/ftrace/ftrace_procfs.h"
#include "src/traced/probes/kmem_activity_trigger.h"
#include "src/traced/probes/probes_producer.h"

namespace perfetto {

int PERFETTO_EXPORT_ENTRYPOINT ProbesMain(int argc, char** argv) {
  enum LongOption {
    OPT_CLEANUP_AFTER_CRASH = 1000,
    OPT_VERSION,
    OPT_BACKGROUND,
    OPT_RESET_FTRACE,
  };

  bool background = false;
  bool reset_ftrace = false;

  static const option long_options[] = {
      {"background", no_argument, nullptr, OPT_BACKGROUND},
      {"cleanup-after-crash", no_argument, nullptr, OPT_CLEANUP_AFTER_CRASH},
      {"reset-ftrace", no_argument, nullptr, OPT_RESET_FTRACE},
      {"version", no_argument, nullptr, OPT_VERSION},
      {nullptr, 0, nullptr, 0}};

  for (;;) {
    int option = getopt_long(argc, argv, "", long_options, nullptr);
    if (option == -1)
      break;
    switch (option) {
      case OPT_BACKGROUND:
        background = true;
        break;
      case OPT_CLEANUP_AFTER_CRASH:
        // Used by perfetto.rc in Android.
        PERFETTO_LOG("Hard resetting ftrace state.");
        HardResetFtraceState();
        return 0;
      case OPT_RESET_FTRACE:
        // This is like --cleanup-after-crash but doesn't quit.
        reset_ftrace = true;
        break;
      case OPT_VERSION:
        printf("%s\n", base::GetVersionString());
        return 0;
      default:
        fprintf(
            stderr,
            "Usage: %s [--background] [--reset-ftrace] [--cleanup-after-crash] "
            "[--version]\n",
            argv[0]);
        return 1;
    }
  }

  if (reset_ftrace && !HardResetFtraceState()) {
    PERFETTO_ELOG(
        "Failed to reset ftrace. Either run this as root or run "
        "`sudo chown -R $USER /sys/kernel/tracing`");
  }

  if (background) {
    base::Daemonize([] { return 0; });
  }

  base::Watchdog* watchdog = base::Watchdog::GetInstance();
  // The memory watchdog will be updated soon after connect, once the shmem
  // buffer size is known, in ProbesProducer::OnTracingSetup().
  watchdog->SetMemoryLimit(base::kWatchdogDefaultMemorySlack,
                           base::kWatchdogDefaultMemoryWindow);
  watchdog->SetCpuLimit(base::kWatchdogDefaultCpuLimit,
                        base::kWatchdogDefaultCpuWindow);
  watchdog->Start();

  PERFETTO_LOG("Starting %s service", argv[0]);

  // This environment variable is set by Android's init to a fd to /dev/kmsg
  // opened for writing (see perfetto.rc). We cannot open the file directly
  // due to permissions.
  const char* env = getenv("ANDROID_FILE__dev_kmsg");
  if (env) {
    FtraceProcfs::g_kmesg_fd = atoi(env);
    // The file descriptor passed by init doesn't have the FD_CLOEXEC bit set.
    // Set it so we don't leak this fd while invoking atrace.
    int res = fcntl(FtraceProcfs::g_kmesg_fd, F_SETFD, FD_CLOEXEC);
    PERFETTO_DCHECK(res == 0);
  }

  base::UnixTaskRunner task_runner;
  ProbesProducer producer;
  // If the TRACED_PROBES_NOTIFY_FD env var is set, write 1 and close the FD,
  // when all data sources have been registered. This is used for //src/tracebox
  // --background-wait, to make sure that the data sources are registered before
  // waiting for them to be started.
  const char* env_notif = getenv("TRACED_PROBES_NOTIFY_FD");
  if (env_notif) {
    int notif_fd = atoi(env_notif);
    producer.SetAllDataSourcesRegisteredCb([notif_fd] {
      PERFETTO_CHECK(base::WriteAll(notif_fd, "1", 1) == 1);
      PERFETTO_CHECK(base::CloseFile(notif_fd) == 0);
    });
  }
  producer.ConnectWithRetries(GetProducerSocket(), &task_runner);

#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
  // Start the thread that polls mm_event instance and triggers
  KmemActivityTrigger kmem_activity_trigger;
#endif

  task_runner.Run();
  return 0;
}

}  // namespace perfetto
