/*
 * Copyright (C) 2021 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 "odr_metrics.h"

#include <unistd.h>

#include <algorithm>
#include <cstdint>
#include <fstream>
#include <iosfwd>
#include <optional>
#include <ostream>
#include <string>

#include <android-base/logging.h>
#include <base/os.h>
#include <odr_fs_utils.h>
#include <odr_metrics_record.h>

namespace art {
namespace odrefresh {

OdrMetrics::OdrMetrics(const std::string& cache_directory, const std::string& metrics_file)
    : cache_directory_(cache_directory), metrics_file_(metrics_file) {
  DCHECK(metrics_file.starts_with("/"));

  // Remove existing metrics file if it exists.
  if (OS::FileExists(metrics_file.c_str())) {
    if (unlink(metrics_file.c_str()) != 0) {
      PLOG(ERROR) << "Failed to remove metrics file '" << metrics_file << "'";
    }
  }

  // Create apexdata dalvik-cache directory if it does not exist. It is required before
  // calling GetFreeSpaceMiB().
  if (!EnsureDirectoryExists(cache_directory)) {
    // This should never fail except for no space on device or configuration issues (e.g. SELinux).
    LOG(WARNING) << "Cache directory '" << cache_directory << "' could not be created.";
  }
  cache_space_free_start_mib_ = GetFreeSpaceMiB(cache_directory);
}

OdrMetrics::~OdrMetrics() {
  CaptureSpaceFreeEnd();

  // Log metrics only if this is explicitly enabled (typically when compilation was done or an error
  // occurred).
  if (enabled_) {
    WriteToFile(metrics_file_, this);
  }
}

void OdrMetrics::CaptureSpaceFreeEnd() {
  cache_space_free_end_mib_ = GetFreeSpaceMiB(cache_directory_);
}

void OdrMetrics::SetDex2OatResult(Stage stage,
                                  int64_t compilation_time_ms,
                                  const std::optional<ExecResult>& dex2oat_result) {
  switch (stage) {
    case Stage::kPrimaryBootClasspath:
      primary_bcp_compilation_millis_ = compilation_time_ms;
      primary_bcp_dex2oat_result_ = dex2oat_result;
      break;
    case Stage::kSecondaryBootClasspath:
      secondary_bcp_compilation_millis_ = compilation_time_ms;
      secondary_bcp_dex2oat_result_ = dex2oat_result;
      break;
    case Stage::kSystemServerClasspath:
      system_server_compilation_millis_ = compilation_time_ms;
      system_server_dex2oat_result_ = dex2oat_result;
      break;
    case Stage::kCheck:
    case Stage::kComplete:
    case Stage::kPreparation:
    case Stage::kUnknown:
      LOG(FATAL) << "Unexpected stage " << stage_ << " when setting dex2oat result";
  }
}

void OdrMetrics::SetBcpCompilationType(Stage stage, BcpCompilationType type) {
  switch (stage) {
    case Stage::kPrimaryBootClasspath:
      primary_bcp_compilation_type_ = type;
      break;
    case Stage::kSecondaryBootClasspath:
      secondary_bcp_compilation_type_ = type;
      break;
    case Stage::kSystemServerClasspath:
    case Stage::kCheck:
    case Stage::kComplete:
    case Stage::kPreparation:
    case Stage::kUnknown:
      LOG(FATAL) << "Unexpected stage " << stage_ << " when setting BCP compilation type";
  }
}

int32_t OdrMetrics::GetFreeSpaceMiB(const std::string& path) {
  static constexpr uint32_t kBytesPerMiB = 1024 * 1024;
  static constexpr uint64_t kNominalMaximumCacheBytes = 1024 * kBytesPerMiB;

  // Assume nominal cache space is 1GiB (much larger than expected, ~100MB).
  uint64_t used_space_bytes;
  if (!GetUsedSpace(path, &used_space_bytes)) {
    used_space_bytes = 0;
  }
  uint64_t nominal_free_space_bytes = kNominalMaximumCacheBytes - used_space_bytes;

  // Get free space on partition containing `path`.
  uint64_t free_space_bytes;
  if (!GetFreeSpace(path, &free_space_bytes)) {
    free_space_bytes = kNominalMaximumCacheBytes;
  }

  // Pick the smallest free space, ie space on partition or nominal space in cache.
  // There are two things of interest for metrics:
  //  (i) identifying failed compilations due to low space.
  // (ii) understanding what the storage requirements are for the spectrum of boot classpaths and
  //      system_server classpaths.
  uint64_t free_space_mib = std::min(free_space_bytes, nominal_free_space_bytes) / kBytesPerMiB;
  return static_cast<int32_t>(free_space_mib);
}

OdrMetricsRecord OdrMetrics::ToRecord() const {
  return {
      .odrefresh_metrics_version = kOdrefreshMetricsVersion,
      .art_apex_version = art_apex_version_,
      .trigger = static_cast<int32_t>(trigger_),
      .stage_reached = static_cast<int32_t>(stage_),
      .status = static_cast<int32_t>(status_),
      .cache_space_free_start_mib = cache_space_free_start_mib_,
      .cache_space_free_end_mib = cache_space_free_end_mib_,
      .primary_bcp_compilation_millis = primary_bcp_compilation_millis_,
      .secondary_bcp_compilation_millis = secondary_bcp_compilation_millis_,
      .system_server_compilation_millis = system_server_compilation_millis_,
      .primary_bcp_dex2oat_result = ConvertExecResult(primary_bcp_dex2oat_result_),
      .secondary_bcp_dex2oat_result = ConvertExecResult(secondary_bcp_dex2oat_result_),
      .system_server_dex2oat_result = ConvertExecResult(system_server_dex2oat_result_),
      .primary_bcp_compilation_type = static_cast<int32_t>(primary_bcp_compilation_type_),
      .secondary_bcp_compilation_type = static_cast<int32_t>(secondary_bcp_compilation_type_),
  };
}

OdrMetricsRecord::Dex2OatExecResult OdrMetrics::ConvertExecResult(
    const std::optional<ExecResult>& result) {
  if (result.has_value()) {
    return OdrMetricsRecord::Dex2OatExecResult(result.value());
  } else {
    return {};
  }
}

void OdrMetrics::WriteToFile(const std::string& path, const OdrMetrics* metrics) {
  OdrMetricsRecord record = metrics->ToRecord();

  const android::base::Result<void>& result = record.WriteToFile(path);
  if (!result.ok()) {
    LOG(ERROR) << "Failed to report metrics to file: " << path
               << ", error: " << result.error().message();
  }
}

}  // namespace odrefresh
}  // namespace art
