# Copyright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Functions for interacting with llvm-profdata"""

import logging
import multiprocessing
import os
import subprocess

logging.basicConfig(
    format='[%(asctime)s %(levelname)s] %(message)s', level=logging.DEBUG)


def _call_profdata_tool(profile_input_file_paths,
                        profile_output_file_path,
                        profdata_tool_path,
                        retries=3):
  """Calls the llvm-profdata tool.

  Args:
    profile_input_file_paths: A list of relative paths to the files that
        are to be merged.
    profile_output_file_path: The path to the merged file to write.
    profdata_tool_path: The path to the llvm-profdata executable.

  Returns:
    A list of paths to profiles that had to be excluded to get the merge to
    succeed, suspected of being corrupted or malformed.

  Raises:
    CalledProcessError: An error occurred merging profiles.
  """
  logging.info('Merging profiles.')

  try:
    subprocess_cmd = [
        profdata_tool_path, 'merge', '-o', profile_output_file_path,
        '-sparse=true'
    ]
    subprocess_cmd.extend(profile_input_file_paths)

    # Redirecting stderr is required because when error happens, llvm-profdata
    # writes the error output to stderr and our error handling logic relies on
    # that output.
    output = subprocess.check_output(subprocess_cmd, stderr=subprocess.STDOUT)
    logging.info('Merge succeeded with output: %r', output)
  except subprocess.CalledProcessError as error:
    if len(profile_input_file_paths) > 1 and retries >= 0:
      logging.warning('Merge failed with error output: %r', error.output)

      # The output of the llvm-profdata command will include the path of
      # malformed files, such as
      # `error: /.../default.profraw: Malformed instrumentation profile data`
      invalid_profiles = [
          f for f in profile_input_file_paths if f in error.output
      ]

      if not invalid_profiles:
        logging.info(
            'Merge failed, but wasn\'t able to figure out the culprit invalid '
            'profiles from the output, so skip retry and bail out.')
        raise error

      valid_profiles = list(
          set(profile_input_file_paths) - set(invalid_profiles))
      if valid_profiles:
        logging.warning(
            'Following invalid profiles are removed as they were mentioned in '
            'the merge error output: %r', invalid_profiles)
        logging.info('Retry merging with the remaining profiles: %r',
                     valid_profiles)
        return invalid_profiles + _call_profdata_tool(
            valid_profiles, profile_output_file_path, profdata_tool_path,
            retries - 1)

    logging.error('Failed to merge profiles, return code (%d), output: %r' %
                  (error.returncode, error.output))
    raise error

  logging.info('Profile data is created as: "%r".', profile_output_file_path)
  return []


def _get_profile_paths(input_dir, input_extension):
  """Finds all the profiles in the given directory (recursively)."""
  paths = []
  for dir_path, _sub_dirs, file_names in os.walk(input_dir):
    paths.extend([
        os.path.join(dir_path, fn)
        for fn in file_names
        if fn.endswith(input_extension)
    ])
  return paths


def _validate_and_convert_profraws(profraw_files, profdata_tool_path):
  """Validates and converts profraws to profdatas.

  For each given .profraw file in the input, this method first validates it by
  trying to convert it to an indexed .profdata file, and if the validation and
  conversion succeeds, the generated .profdata file will be included in the
  output, otherwise, won't.

  This method is mainly used to filter out invalid profraw files.

  Args:
    profraw_files: A list of .profraw paths.
    profdata_tool_path: The path to the llvm-profdata executable.

  Returns:
    A tulple:
      A list of converted .profdata files of *valid* profraw files.
      A list of *invalid* profraw files.
  """
  logging.info('Validating and converting .profraw files.')

  for profraw_file in profraw_files:
    if not profraw_file.endswith('.profraw'):
      raise RuntimeError('%r is expected to be a .profraw file.' % profraw_file)

  cpu_count = multiprocessing.cpu_count()
  counts = max(10, cpu_count - 5)  # Use 10+ processes, but leave 5 cpu cores.
  pool = multiprocessing.Pool(counts)
  output_profdata_files = multiprocessing.Manager().list()
  invalid_profraw_files = multiprocessing.Manager().list()

  for profraw_file in profraw_files:
    pool.apply_async(_validate_and_convert_profraw,
                     (profraw_file, output_profdata_files,
                      invalid_profraw_files, profdata_tool_path))

  pool.close()
  pool.join()

  # Remove inputs, as they won't be needed and they can be pretty large.
  for input_file in profraw_files:
    os.remove(input_file)

  return list(output_profdata_files), list(invalid_profraw_files)


def _validate_and_convert_profraw(profraw_file, output_profdata_files,
                                  invalid_profraw_files, profdata_tool_path):
  output_profdata_file = profraw_file.replace('.profraw', '.profdata')
  subprocess_cmd = [
      profdata_tool_path, 'merge', '-o', output_profdata_file, '-sparse=true',
      profraw_file
  ]

  try:
    # Redirecting stderr is required because when error happens, llvm-profdata
    # writes the error output to stderr and our error handling logic relies on
    # that output.
    output = subprocess.check_output(subprocess_cmd, stderr=subprocess.STDOUT)
    logging.info('Validating and converting %r to %r succeeded with output: %r',
                 profraw_file, output_profdata_file, output)
    output_profdata_files.append(output_profdata_file)
  except subprocess.CalledProcessError as error:
    logging.warning('Validating and converting %r to %r failed with output: %r',
                    profraw_file, output_profdata_file, error.output)
    invalid_profraw_files.append(profraw_file)


def merge_profiles(input_dir, output_file, input_extension, profdata_tool_path):
  """Merges the profiles produced by the shards using llvm-profdata.

  Args:
    input_dir (str): The path to traverse to find input profiles.
    output_file (str): Where to write the merged profile.
    input_extension (str): File extension to look for in the input_dir.
        e.g. '.profdata' or '.profraw'
    profdata_tool_path: The path to the llvm-profdata executable.
  Returns:
    The list of profiles that had to be excluded to get the merge to
    succeed.
  """
  profile_input_file_paths = _get_profile_paths(input_dir, input_extension)
  invalid_profraw_files = []
  if input_extension == '.profraw':
    profile_input_file_paths, invalid_profraw_files = (
        _validate_and_convert_profraws(profile_input_file_paths,
                                       profdata_tool_path))
    logging.info('List of converted .profdata files: %r',
                 profile_input_file_paths)
    logging.info((
        'List of invalid .profraw files that failed to validate and convert: %r'
    ), invalid_profraw_files)

  invalid_profdata_files = _call_profdata_tool(
      profile_input_file_paths=profile_input_file_paths,
      profile_output_file_path=output_file,
      profdata_tool_path=profdata_tool_path)

  # Remove inputs, as they won't be needed and they can be pretty large.
  for input_file in profile_input_file_paths:
    os.remove(input_file)

  return invalid_profraw_files + invalid_profdata_files
