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

#include "base/os.h"
#include "base/unix_file/fd_file.h"

namespace art {

// Minimum number of new methods/classes that profiles
// must contain to enable recompilation.
static constexpr const uint32_t kMinNewMethodsForCompilation = 100;
static constexpr const uint32_t kMinNewClassesForCompilation = 50;


ProfileAssistant::ProcessingResult ProfileAssistant::ProcessProfilesInternal(
        const std::vector<ScopedFlock>& profile_files,
        const ScopedFlock& reference_profile_file,
        const ProfileCompilationInfo::ProfileLoadFilterFn& filter_fn,
        const Options& options) {
  DCHECK(!profile_files.empty());

  ProfileCompilationInfo info(options.IsBootImageMerge());

  // Load the reference profile.
  if (!info.Load(reference_profile_file->Fd(), /*merge_classes=*/ true, filter_fn)) {
    LOG(WARNING) << "Could not load reference profile file";
    return kErrorBadProfiles;
  }

  if (options.IsBootImageMerge() && !info.IsForBootImage()) {
    LOG(WARNING) << "Requested merge for boot image profile but the reference profile is regular.";
    return kErrorBadProfiles;
  }

  // Store the current state of the reference profile before merging with the current profiles.
  uint32_t number_of_methods = info.GetNumberOfMethods();
  uint32_t number_of_classes = info.GetNumberOfResolvedClasses();

  // Merge all current profiles.
  for (size_t i = 0; i < profile_files.size(); i++) {
    ProfileCompilationInfo cur_info;
    if (!cur_info.Load(profile_files[i]->Fd(), /*merge_classes=*/ true, filter_fn)) {
      LOG(WARNING) << "Could not load profile file at index " << i;
      if (options.IsForceMerge()) {
        // If we have to merge forcefully, ignore load failures.
        // This is useful for boot image profiles to ignore stale profiles which are
        // cleared lazily.
        continue;
      }
      return kErrorBadProfiles;
    }

    // Check version mismatch.
    // This may happen during profile analysis if one profile is regular and
    // the other one is for the boot image. For example when switching on-off
    // the boot image profiles.
    if (!info.SameVersion(cur_info)) {
      if (options.IsForceMerge()) {
        // If we have to merge forcefully, ignore the current profile and
        // continue to the next one.
        continue;
      } else {
        // Otherwise, return an error.
        return kErrorDifferentVersions;
      }
    }

    if (!info.MergeWith(cur_info)) {
      LOG(WARNING) << "Could not merge profile file at index " << i;
      return kErrorBadProfiles;
    }
  }

  // If we perform a forced merge do not analyze the difference between profiles.
  if (!options.IsForceMerge()) {
    uint32_t min_change_in_methods_for_compilation = std::max(
        (options.GetMinNewMethodsPercentChangeForCompilation() * number_of_methods) / 100,
        kMinNewMethodsForCompilation);
    uint32_t min_change_in_classes_for_compilation = std::max(
        (options.GetMinNewClassesPercentChangeForCompilation() * number_of_classes) / 100,
        kMinNewClassesForCompilation);
    // Check if there is enough new information added by the current profiles.
    if (((info.GetNumberOfMethods() - number_of_methods) < min_change_in_methods_for_compilation) &&
        ((info.GetNumberOfResolvedClasses() - number_of_classes)
            < min_change_in_classes_for_compilation)) {
      return kSkipCompilation;
    }
  }

  // We were successful in merging all profile information. Update the reference profile.
  if (!reference_profile_file->ClearContent()) {
    PLOG(WARNING) << "Could not clear reference profile file";
    return kErrorIO;
  }
  if (!info.Save(reference_profile_file->Fd())) {
    LOG(WARNING) << "Could not save reference profile file";
    return kErrorIO;
  }

  return options.IsForceMerge() ? kSuccess : kCompile;
}

class ScopedFlockList {
 public:
  explicit ScopedFlockList(size_t size) : flocks_(size) {}

  // Will block until all the locks are acquired.
  bool Init(const std::vector<std::string>& filenames, /* out */ std::string* error) {
    for (size_t i = 0; i < filenames.size(); i++) {
      flocks_[i] = LockedFile::Open(filenames[i].c_str(), O_RDWR, /* block= */ true, error);
      if (flocks_[i].get() == nullptr) {
        *error += " (index=" + std::to_string(i) + ")";
        return false;
      }
    }
    return true;
  }

  // Will block until all the locks are acquired.
  bool Init(const std::vector<int>& fds, /* out */ std::string* error) {
    for (size_t i = 0; i < fds.size(); i++) {
      DCHECK_GE(fds[i], 0);
      flocks_[i] = LockedFile::DupOf(fds[i], "profile-file",
                                     /* read_only_mode= */ true, error);
      if (flocks_[i].get() == nullptr) {
        *error += " (index=" + std::to_string(i) + ")";
        return false;
      }
    }
    return true;
  }

  const std::vector<ScopedFlock>& Get() const { return flocks_; }

 private:
  std::vector<ScopedFlock> flocks_;
};

ProfileAssistant::ProcessingResult ProfileAssistant::ProcessProfiles(
        const std::vector<int>& profile_files_fd,
        int reference_profile_file_fd,
        const ProfileCompilationInfo::ProfileLoadFilterFn& filter_fn,
        const Options& options) {
  DCHECK_GE(reference_profile_file_fd, 0);

  std::string error;
  ScopedFlockList profile_files(profile_files_fd.size());
  if (!profile_files.Init(profile_files_fd, &error)) {
    LOG(WARNING) << "Could not lock profile files: " << error;
    return kErrorCannotLock;
  }

  // The reference_profile_file is opened in read/write mode because it's
  // cleared after processing.
  ScopedFlock reference_profile_file = LockedFile::DupOf(reference_profile_file_fd,
                                                         "reference-profile",
                                                         /* read_only_mode= */ false,
                                                         &error);
  if (reference_profile_file.get() == nullptr) {
    LOG(WARNING) << "Could not lock reference profiled files: " << error;
    return kErrorCannotLock;
  }

  return ProcessProfilesInternal(profile_files.Get(),
                                 reference_profile_file,
                                 filter_fn,
                                 options);
}

ProfileAssistant::ProcessingResult ProfileAssistant::ProcessProfiles(
        const std::vector<std::string>& profile_files,
        const std::string& reference_profile_file,
        const ProfileCompilationInfo::ProfileLoadFilterFn& filter_fn,
        const Options& options) {
  std::string error;

  ScopedFlockList profile_files_list(profile_files.size());
  if (!profile_files_list.Init(profile_files, &error)) {
    LOG(WARNING) << "Could not lock profile files: " << error;
    return kErrorCannotLock;
  }

  ScopedFlock locked_reference_profile_file = LockedFile::Open(
      reference_profile_file.c_str(), O_RDWR, /* block= */ true, &error);
  if (locked_reference_profile_file.get() == nullptr) {
    LOG(WARNING) << "Could not lock reference profile files: " << error;
    return kErrorCannotLock;
  }

  return ProcessProfilesInternal(profile_files_list.Get(),
                                 locked_reference_profile_file,
                                 filter_fn,
                                 options);
}

}  // namespace art
