/*
 * 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.
 */

#ifndef ART_ODREFRESH_ODR_METRICS_H_
#define ART_ODREFRESH_ODR_METRICS_H_

#include <chrono>
#include <cstdint>
#include <iosfwd>
#include <optional>
#include <string>

#include "base/macros.h"
#include "exec_utils.h"
#include "odr_metrics_record.h"

namespace art {
namespace odrefresh {

class OdrMetrics final {
 public:
  // Enumeration used to track the latest stage reached running odrefresh.
  //
  // These values mirror those in OdrefreshReported::Stage in frameworks/proto_logging/atoms.proto.
  // NB There are gaps between the values in case an additional stages are introduced.
  enum class Stage : uint8_t {
    kUnknown = 0,
    kCheck = 10,
    kPreparation = 20,
    kPrimaryBootClasspath = 30,
    kSecondaryBootClasspath = 40,
    kSystemServerClasspath = 50,
    kComplete = 60,
  };

  // Enumeration describing the overall status, processing stops on the first error discovered.
  //
  // These values mirror those in OdrefreshReported::Status in frameworks/proto_logging/atoms.proto.
  enum class Status : uint8_t {
    kUnknown = 0,
    kOK = 1,
    kNoSpace = 2,
    kIoError = 3,
    kDex2OatError = 4,
    // Value 5 was kTimeLimitExceeded, but has been removed in favour of
    // reporting the exit code for Dex2Oat (set to ExecResult::kTimedOut)
    kStagingFailed = 6,
    kInstallFailed = 7,
    // Failed to access the dalvik-cache directory due to lack of permission.
    kDalvikCachePermissionDenied = 8,
  };

  // Enumeration describing the cause of compilation (if any) in odrefresh.
  //
  // These values mirror those in OdrefreshReported::Trigger in
  // frameworks/proto_logging/atoms.proto.
  enum class Trigger : uint8_t {
    kUnknown = 0,
    kApexVersionMismatch = 1,
    kDexFilesChanged = 2,
    kMissingArtifacts = 3,
  };

  explicit OdrMetrics(const std::string& cache_directory,
                      const std::string& metrics_file = kOdrefreshMetricsFile);
  ~OdrMetrics();

  // Enables/disables metrics writing.
  void SetEnabled(bool value) { enabled_ = value; }

  // Gets the ART APEX that metrics are being collected on behalf of.
  int64_t GetArtApexVersion() const { return art_apex_version_; }

  // Sets the ART APEX that metrics are being collected on behalf of.
  void SetArtApexVersion(int64_t version) { art_apex_version_ = version; }

  // Gets the ART APEX last update time in milliseconds.
  int64_t GetArtApexLastUpdateMillis() const { return art_apex_last_update_millis_; }

  // Sets the ART APEX last update time in milliseconds.
  void SetArtApexLastUpdateMillis(int64_t last_update_millis) {
    art_apex_last_update_millis_ = last_update_millis;
  }

  // Gets the trigger for metrics collection. The trigger is the reason why odrefresh considers
  // compilation necessary.
  Trigger GetTrigger() const { return trigger_; }

  // Sets the trigger for metrics collection. The trigger is the reason why odrefresh considers
  // compilation necessary. Only call this method if compilation is necessary as the presence
  // of a trigger means we will try to record and upload metrics.
  void SetTrigger(const Trigger trigger) { trigger_ = trigger; }

  // Sets the execution status of the current odrefresh processing stage.
  void SetStatus(const Status status) { status_ = status; }

  // Sets the current odrefresh processing stage.
  void SetStage(Stage stage) { stage_ = stage; }

  // Sets the result of the current dex2oat invocation.
  void SetDex2OatResult(const ExecResult& dex2oat_result);

  // Captures the current free space as the end free space.
  void CaptureSpaceFreeEnd();

  // Records metrics into an OdrMetricsRecord.
  OdrMetricsRecord ToRecord() const;

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

  static int32_t GetFreeSpaceMiB(const std::string& path);
  static void WriteToFile(const std::string& path, const OdrMetrics* metrics);

  void SetCompilationTime(int32_t millis);
  static OdrMetricsRecord::Dex2OatExecResult
  ConvertExecResult(const std::optional<ExecResult>& result);

  const std::string cache_directory_;
  const std::string metrics_file_;

  bool enabled_ = false;

  int64_t art_apex_version_ = 0;
  int64_t art_apex_last_update_millis_ = 0;
  Trigger trigger_ = Trigger::kUnknown;
  Stage stage_ = Stage::kUnknown;
  Status status_ = Status::kUnknown;

  int32_t cache_space_free_start_mib_ = 0;
  int32_t cache_space_free_end_mib_ = 0;

  // The total time spent on compiling primary BCP.
  int32_t primary_bcp_compilation_millis_ = 0;

  // The result of the dex2oat invocation for compiling primary BCP, or `std::nullopt` if dex2oat is
  // not invoked.
  std::optional<ExecResult> primary_bcp_dex2oat_result_;

  // The total time spent on compiling secondary BCP.
  int32_t secondary_bcp_compilation_millis_ = 0;

  // The result of the dex2oat invocation for compiling secondary BCP, or `std::nullopt` if dex2oat
  // is not invoked.
  std::optional<ExecResult> secondary_bcp_dex2oat_result_;

  // The total time spent on compiling system server.
  int32_t system_server_compilation_millis_ = 0;

  // The result of the last dex2oat invocation for compiling system server, or `std::nullopt` if
  // dex2oat is not invoked.
  std::optional<ExecResult> system_server_dex2oat_result_;

  friend class ScopedOdrCompilationTimer;
};

// Timer used to measure compilation time (in seconds). Automatically associates the time recorded
// with the current stage of the metrics used.
class ScopedOdrCompilationTimer final {
 public:
  explicit ScopedOdrCompilationTimer(OdrMetrics& metrics) :
    metrics_(metrics), start_(std::chrono::steady_clock::now()) {}

  ~ScopedOdrCompilationTimer() {
    auto elapsed_time = std::chrono::steady_clock::now() - start_;
    auto elapsed_millis = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed_time);
    metrics_.SetCompilationTime(static_cast<int32_t>(elapsed_millis.count()));
  }

 private:
  OdrMetrics& metrics_;
  std::chrono::time_point<std::chrono::steady_clock> start_;

  DISALLOW_ALLOCATION();
};

// Generated ostream operators.
std::ostream& operator<<(std::ostream& os, OdrMetrics::Status status);
std::ostream& operator<<(std::ostream& os, OdrMetrics::Stage stage);
std::ostream& operator<<(std::ostream& os, OdrMetrics::Trigger trigger);

}  // namespace odrefresh
}  // namespace art

#endif  // ART_ODREFRESH_ODR_METRICS_H_
