/*
 * 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_COMPILATION_LOG_H_
#define ART_ODREFRESH_ODR_COMPILATION_LOG_H_

#include <time.h>

#include <cstdint>
#include <iosfwd>
#include <vector>

#include <odrefresh/odrefresh.h>
#include <odr_metrics.h>

namespace art {
namespace odrefresh {

// OdrCompilationLogEntry represents the result of a compilation attempt by odrefresh.
struct OdrCompilationLogEntry {
  int64_t apex_version;
  int32_t trigger;
  time_t when;
  int32_t exit_code;
};

// Read an `OdrCompilationLogEntry` from an input stream.
std::istream& operator>>(std::istream& is, OdrCompilationLogEntry& entry);

// Write an `OdrCompilationLogEntry` to an output stream.
std::ostream& operator<<(std::ostream& os, const OdrCompilationLogEntry& entry);

// Equality test for two `OdrCompilationLogEntry` instances.
bool operator==(const OdrCompilationLogEntry& lhs, const OdrCompilationLogEntry& rhs);
bool operator!=(const OdrCompilationLogEntry& lhs, const OdrCompilationLogEntry& rhs);

class OdrCompilationLog {
 public:
  // The compilation log location is in the same directory as used for the metricss.log. This
  // directory is only used by odrefresh whereas the ART apexdata directory is also used by odsign
  // and others which may lead to the deletion (or rollback) of the log file.
  static constexpr const char* kCompilationLogFile = "/data/misc/odrefresh/compilation-log.txt";
  static constexpr const size_t kMaxLoggedEntries = 4;

  explicit OdrCompilationLog(const char* compilation_log_path = kCompilationLogFile);
  ~OdrCompilationLog();

  // Applies policy to compilation log to determine whether to recompile.
  bool ShouldAttemptCompile(int64_t apex_version,
                            OdrMetrics::Trigger trigger,
                            time_t now = 0) const;

  // Returns the number of entries in the log. The log never exceeds `kMaxLoggedEntries`.
  size_t NumberOfEntries() const;

  // Returns the entry at position `index` or nullptr if `index` is out of bounds.
  const OdrCompilationLogEntry* Peek(size_t index) const;

  void Log(int64_t apex_version, OdrMetrics::Trigger trigger, ExitCode compilation_result);

  void Log(int64_t apex_version,
           OdrMetrics::Trigger trigger,
           time_t when,
           ExitCode compilation_result);

  // Truncates the in memory log to have `kMaxLoggedEntries` records.
  void Truncate();

 private:
  bool Read();
  bool Write() const;

  std::vector<OdrCompilationLogEntry> entries_;
  const char* log_path_;
};

}  // namespace odrefresh
}  // namespace art

#endif  // ART_ODREFRESH_ODR_COMPILATION_LOG_H_
