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

#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include "perfetto/base/logging.h"
#include "perfetto/base/scoped_file.h"
#include "perfetto/base/utils.h"
#include "src/perfetto_cmd/perfetto_cmd.h"

namespace perfetto {
namespace {

// 5 mins between traces.
const uint64_t kCooldownInSeconds = 60 * 5;

// Every 24 hours we reset how much we've uploaded.
const uint64_t kMaxUploadResetPeriodInSeconds = 60 * 60 * 24;

// Maximum of 10mb every 24h.
const uint64_t kMaxUploadInBytes = 1024 * 1024 * 10;

}  // namespace

RateLimiter::RateLimiter() = default;
RateLimiter::~RateLimiter() = default;

bool RateLimiter::ShouldTrace(const Args& args) {
  uint64_t now_in_s = args.current_time.count();

  // Not uploading?
  // -> We can just trace.
  if (!args.is_dropbox)
    return true;

  // The state file is gone.
  // Maybe we're tracing for the first time or maybe something went wrong the
  // last time we tried to save the state. Either way reinitialize the state
  // file.
  if (!StateFileExists()) {
    // We can't write the empty state file?
    // -> Give up.
    if (!ClearState()) {
      PERFETTO_ELOG("Guardrail: failed to initialize guardrail state.");
      return false;
    }
  }

  bool loaded_state = LoadState(&state_);

  // Failed to load the state?
  // Current time is before either saved times?
  // Last saved trace time is before first saved trace time?
  // -> Try to save a clean state but don't trace.
  if (!loaded_state || now_in_s < state_.first_trace_timestamp() ||
      now_in_s < state_.last_trace_timestamp() ||
      state_.last_trace_timestamp() < state_.first_trace_timestamp()) {
    ClearState();
    PERFETTO_ELOG("Guardrail: state invalid, clearing it.");
    if (!args.ignore_guardrails)
      return false;
  }

  // If we've uploaded in the last 5mins we shouldn't trace now.
  if ((now_in_s - state_.last_trace_timestamp()) < kCooldownInSeconds) {
    PERFETTO_ELOG("Guardrail: Uploaded to DropBox in the last 5mins.");
    if (!args.ignore_guardrails)
      return false;
  }

  // First trace was more than 24h ago? Reset state.
  if ((now_in_s - state_.first_trace_timestamp()) >
      kMaxUploadResetPeriodInSeconds) {
    state_.set_first_trace_timestamp(0);
    state_.set_last_trace_timestamp(0);
    state_.set_total_bytes_uploaded(0);
    return true;
  }

  // If we've uploaded more than 10mb in the last 24 hours we shouldn't trace
  // now.
  if (state_.total_bytes_uploaded() > kMaxUploadInBytes) {
    PERFETTO_ELOG("Guardrail: Uploaded >10mb DropBox in the last 24h.");
    if (!args.ignore_guardrails)
      return false;
  }

  return true;
}

bool RateLimiter::OnTraceDone(const Args& args, bool success, size_t bytes) {
  uint64_t now_in_s = args.current_time.count();

  // Failed to upload? Don't update the state.
  if (!success)
    return false;

  if (!args.is_dropbox)
    return true;

  // If the first trace timestamp is 0 (either because this is the
  // first time or because it was reset for being more than 24h ago).
  // -> We update it to the time of this trace.
  if (state_.first_trace_timestamp() == 0)
    state_.set_first_trace_timestamp(now_in_s);
  // Always updated the last trace timestamp.
  state_.set_last_trace_timestamp(now_in_s);
  // Add the amount we uploaded to the running total.
  state_.set_total_bytes_uploaded(state_.total_bytes_uploaded() + bytes);

  if (!SaveState(state_)) {
    PERFETTO_ELOG("Failed to save state.");
    return false;
  }

  return true;
}

std::string RateLimiter::GetStateFilePath() const {
  return std::string(kTempDropBoxTraceDir) + "/.guardraildata";
}

bool RateLimiter::StateFileExists() {
  struct stat out;
  return stat(GetStateFilePath().c_str(), &out) != -1;
}

bool RateLimiter::ClearState() {
  PerfettoCmdState zero{};
  zero.set_total_bytes_uploaded(0);
  zero.set_last_trace_timestamp(0);
  zero.set_first_trace_timestamp(0);
  bool success = SaveState(zero);
  if (!success && StateFileExists())
    remove(GetStateFilePath().c_str());
  return success;
}

bool RateLimiter::LoadState(PerfettoCmdState* state) {
  base::ScopedFile in_fd;
  in_fd.reset(open(GetStateFilePath().c_str(), O_RDONLY));

  if (!in_fd)
    return false;
  char buf[1024];
  ssize_t bytes = PERFETTO_EINTR(read(in_fd.get(), &buf, sizeof(buf)));
  if (bytes <= 0)
    return false;
  return state->ParseFromArray(&buf, bytes);
}

bool RateLimiter::SaveState(const PerfettoCmdState& state) {
  base::ScopedFile out_fd;
  out_fd.reset(
      open(GetStateFilePath().c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0600));
  if (!out_fd)
    return false;
  char buf[1024];
  PERFETTO_CHECK(static_cast<size_t>(state.ByteSize()) < sizeof(buf));
  size_t size = state.ByteSize();
  if (!state.SerializeToArray(&buf, size))
    return false;
  ssize_t written = PERFETTO_EINTR(write(out_fd.get(), &buf, size));
  return written >= 0 && static_cast<size_t>(written) == size;
}

}  // namespace perfetto
