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

#include <fstream>
#include <vector>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/uio.h>

#include "art_method-inl.h"
#include "base/mutex.h"
#include "base/scoped_flock.h"
#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
#include "jit/profiling_info.h"
#include "os.h"
#include "safe_map.h"

namespace art {

// Transform the actual dex location into relative paths.
// Note: this is OK because we don't store profiles of different apps into the same file.
// Apps with split apks don't cause trouble because each split has a different name and will not
// collide with other entries.
std::string ProfileCompilationInfo::GetProfileDexFileKey(const std::string& dex_location) {
  DCHECK(!dex_location.empty());
  size_t last_sep_index = dex_location.find_last_of('/');
  if (last_sep_index == std::string::npos) {
    return dex_location;
  } else {
    DCHECK(last_sep_index < dex_location.size());
    return dex_location.substr(last_sep_index + 1);
  }
}

bool ProfileCompilationInfo::SaveProfilingInfo(const std::string& filename,
                                               const std::vector<ArtMethod*>& methods) {
  if (methods.empty()) {
    VLOG(profiler) << "No info to save to " << filename;
    return true;
  }

  ScopedFlock flock;
  std::string error;
  if (!flock.Init(filename.c_str(), O_RDWR | O_NOFOLLOW | O_CLOEXEC, /* block */ false, &error)) {
    LOG(WARNING) << "Couldn't lock the profile file " << filename << ": " << error;
    return false;
  }

  int fd = flock.GetFile()->Fd();

  ProfileCompilationInfo info;
  if (!info.Load(fd)) {
    LOG(WARNING) << "Could not load previous profile data from file " << filename;
    return false;
  }
  {
    ScopedObjectAccess soa(Thread::Current());
    for (auto it = methods.begin(); it != methods.end(); it++) {
      const DexFile* dex_file = (*it)->GetDexFile();
      if (!info.AddData(GetProfileDexFileKey(dex_file->GetLocation()),
                        dex_file->GetLocationChecksum(),
                        (*it)->GetDexMethodIndex())) {
        return false;
      }
    }
  }

  if (!flock.GetFile()->ClearContent()) {
    PLOG(WARNING) << "Could not clear profile file: " << filename;
    return false;
  }

  // This doesn't need locking because we are trying to lock the file for exclusive
  // access and fail immediately if we can't.
  bool result = info.Save(fd);
  if (result) {
    VLOG(profiler) << "Successfully saved profile info to " << filename
        << " Size: " << GetFileSizeBytes(filename);
  } else {
    VLOG(profiler) << "Failed to save profile info to " << filename;
  }
  return result;
}

static bool WriteToFile(int fd, const std::ostringstream& os) {
  std::string data(os.str());
  const char *p = data.c_str();
  size_t length = data.length();
  do {
    int n = TEMP_FAILURE_RETRY(write(fd, p, length));
    if (n < 0) {
      PLOG(WARNING) << "Failed to write to descriptor: " << fd;
      return false;
    }
    p += n;
    length -= n;
  } while (length > 0);
  return true;
}

static constexpr const char kFieldSeparator = ',';
static constexpr const char kLineSeparator = '\n';

/**
 * Serialization format:
 *    dex_location1,dex_location_checksum1,method_id11,method_id12...
 *    dex_location2,dex_location_checksum2,method_id21,method_id22...
 * e.g.
 *    app.apk,131232145,11,23,454,54
 *    app.apk:classes5.dex,218490184,39,13,49,1
 **/
bool ProfileCompilationInfo::Save(uint32_t fd) {
  DCHECK_GE(fd, 0u);
  // TODO(calin): Profile this and see how much memory it takes. If too much,
  // write to file directly.
  std::ostringstream os;
  for (const auto& it : info_) {
    const std::string& dex_location = it.first;
    const DexFileData& dex_data = it.second;

    os << dex_location << kFieldSeparator << dex_data.checksum;
    for (auto method_it : dex_data.method_set) {
      os << kFieldSeparator << method_it;
    }
    os << kLineSeparator;
  }

  return WriteToFile(fd, os);
}

// TODO(calin): This a duplicate of Utils::Split fixing the case where the first character
// is the separator. Merge the fix into Utils::Split once verified that it doesn't break its users.
static void SplitString(const std::string& s, char separator, std::vector<std::string>* result) {
  const char* p = s.data();
  const char* end = p + s.size();
  // Check if the first character is the separator.
  if (p != end && *p ==separator) {
    result->push_back("");
    ++p;
  }
  // Process the rest of the characters.
  while (p != end) {
    if (*p == separator) {
      ++p;
    } else {
      const char* start = p;
      while (++p != end && *p != separator) {
        // Skip to the next occurrence of the separator.
      }
      result->push_back(std::string(start, p - start));
    }
  }
}

bool ProfileCompilationInfo::AddData(const std::string& dex_location,
                                     uint32_t checksum,
                                     uint16_t method_idx) {
  auto info_it = info_.find(dex_location);
  if (info_it == info_.end()) {
    info_it = info_.Put(dex_location, DexFileData(checksum));
  }
  if (info_it->second.checksum != checksum) {
    LOG(WARNING) << "Checksum mismatch for dex " << dex_location;
    return false;
  }
  info_it->second.method_set.insert(method_idx);
  return true;
}

bool ProfileCompilationInfo::ProcessLine(const std::string& line) {
  std::vector<std::string> parts;
  SplitString(line, kFieldSeparator, &parts);
  if (parts.size() < 3) {
    LOG(WARNING) << "Invalid line: " << line;
    return false;
  }

  const std::string& dex_location = parts[0];
  uint32_t checksum;
  if (!ParseInt(parts[1].c_str(), &checksum)) {
    return false;
  }

  for (size_t i = 2; i < parts.size(); i++) {
    uint32_t method_idx;
    if (!ParseInt(parts[i].c_str(), &method_idx)) {
      LOG(WARNING) << "Cannot parse method_idx " << parts[i];
      return false;
    }
    if (!AddData(dex_location, checksum, method_idx)) {
      return false;
    }
  }
  return true;
}

// Parses the buffer (of length n) starting from start_from and identify new lines
// based on kLineSeparator marker.
// Returns the first position after kLineSeparator in the buffer (starting from start_from),
// or -1 if the marker doesn't appear.
// The processed characters are appended to the given line.
static int GetLineFromBuffer(char* buffer, int n, int start_from, std::string& line) {
  if (start_from >= n) {
    return -1;
  }
  int new_line_pos = -1;
  for (int i = start_from; i < n; i++) {
    if (buffer[i] == kLineSeparator) {
      new_line_pos = i;
      break;
    }
  }
  int append_limit = new_line_pos == -1 ? n : new_line_pos;
  line.append(buffer + start_from, append_limit - start_from);
  // Jump over kLineSeparator and return the position of the next character.
  return new_line_pos == -1 ? new_line_pos : new_line_pos + 1;
}

bool ProfileCompilationInfo::Load(uint32_t fd) {
  DCHECK_GE(fd, 0u);

  std::string current_line;
  const int kBufferSize = 1024;
  char buffer[kBufferSize];

  while (true) {
    int n = TEMP_FAILURE_RETRY(read(fd, buffer, kBufferSize));
    if (n < 0) {
      PLOG(WARNING) << "Error when reading profile file";
      return false;
    } else if (n == 0) {
      break;
    }
    // Detect the new lines from the buffer. If we manage to complete a line,
    // process it. Otherwise append to the current line.
    int current_start_pos = 0;
    while (current_start_pos < n) {
      current_start_pos = GetLineFromBuffer(buffer, n, current_start_pos, current_line);
      if (current_start_pos == -1) {
        break;
      }
      if (!ProcessLine(current_line)) {
        return false;
      }
      // Reset the current line (we just processed it).
      current_line.clear();
    }
  }
  return true;
}

bool ProfileCompilationInfo::Load(const ProfileCompilationInfo& other) {
  for (const auto& other_it : other.info_) {
    const std::string& other_dex_location = other_it.first;
    const DexFileData& other_dex_data = other_it.second;

    auto info_it = info_.find(other_dex_location);
    if (info_it == info_.end()) {
      info_it = info_.Put(other_dex_location, DexFileData(other_dex_data.checksum));
    }
    if (info_it->second.checksum != other_dex_data.checksum) {
      LOG(WARNING) << "Checksum mismatch for dex " << other_dex_location;
      return false;
    }
    info_it->second.method_set.insert(other_dex_data.method_set.begin(),
                                      other_dex_data.method_set.end());
  }
  return true;
}

bool ProfileCompilationInfo::ContainsMethod(const MethodReference& method_ref) const {
  auto info_it = info_.find(GetProfileDexFileKey(method_ref.dex_file->GetLocation()));
  if (info_it != info_.end()) {
    if (method_ref.dex_file->GetLocationChecksum() != info_it->second.checksum) {
      return false;
    }
    const std::set<uint16_t>& methods = info_it->second.method_set;
    return methods.find(method_ref.dex_method_index) != methods.end();
  }
  return false;
}

uint32_t ProfileCompilationInfo::GetNumberOfMethods() const {
  uint32_t total = 0;
  for (const auto& it : info_) {
    total += it.second.method_set.size();
  }
  return total;
}

std::string ProfileCompilationInfo::DumpInfo(const std::vector<const DexFile*>* dex_files,
                                             bool print_full_dex_location) const {
  std::ostringstream os;
  if (info_.empty()) {
    return "ProfileInfo: empty";
  }

  os << "ProfileInfo:";

  const std::string kFirstDexFileKeySubstitute = ":classes.dex";
  for (const auto& it : info_) {
    os << "\n";
    const std::string& location = it.first;
    const DexFileData& dex_data = it.second;
    if (print_full_dex_location) {
      os << location;
    } else {
      // Replace the (empty) multidex suffix of the first key with a substitute for easier reading.
      std::string multidex_suffix = DexFile::GetMultiDexSuffix(location);
      os << (multidex_suffix.empty() ? kFirstDexFileKeySubstitute : multidex_suffix);
    }
    for (const auto method_it : dex_data.method_set) {
      if (dex_files != nullptr) {
        const DexFile* dex_file = nullptr;
        for (size_t i = 0; i < dex_files->size(); i++) {
          if (location == (*dex_files)[i]->GetLocation()) {
            dex_file = (*dex_files)[i];
          }
        }
        if (dex_file != nullptr) {
          os << "\n  " << PrettyMethod(method_it, *dex_file, true);
        }
      }
      os << "\n  " << method_it;
    }
  }
  return os.str();
}

bool ProfileCompilationInfo::Equals(ProfileCompilationInfo& other) {
  return info_.Equals(other.info_);
}

}  // namespace art
