=head1 NAME

  CFX5::Parallel::Reqs::impi_winhydra - Check Intel MPI hydra service

This prerequisite performs the checks required for Intel MPI
parallel on Windows, where the hydra service needs to be installed
and user credentials cached.

=cut

package CFX5::Parallel::Reqs::impi_winhydra;

use CFX5::Parallel::Reqs::Base;
push @ISA, qw(CFX5::Parallel::Reqs::Base);

use CFX5::Config qw(%Config);
use CFX5::Output qw(:all);
use CFX5::FileTests;
use CFX5::PkgLoader qw(cfx5_require);
use CFX5::PathManip qw(join_file);
use CFX5::Commands qw(get_cmd_output);

use strict;

sub setup {
  my $self=shift;
  my $workdir=shift;

  unless ($Config{windows_nt}) {
    internal_error("Can only perform Intel MPI SPMD checks on Windows");
  }

  # If either delegate or impersonate authentication is used, the user credentials
  # don't need to be registered (and we don't need to check them).
  my $auth_method = $ENV{I_MPI_AUTH_METHOD};
  if (defined $auth_method) {
    return 1 if ($auth_method eq 'delegate' or $auth_method eq 'impersonate');
  }

  # Check user credentials are registered.
  # Intel MPI uses two different caching mechanisms for credentials.
  # First, try (1) and if nothing is found, try (2).

  # 1. Used by 'mpiexec -register' and comprises the following registry keys:
  #   HKEY_CURRENT_USER\Software\Intel\MPI\hydraAccount
  #   HKEY_CURRENT_USER\Software\Intel\MPI\hydraPassword
  # This entry is recognized by mpiexec.exe -validate

  my $valid_exec = join_file($Config{CFX5_IMPI_DIR}, 'bin', 'mpiexec.exe');
  unless (CFX5::FileTests::execfile($valid_exec, "A required binary for Intel MPI Parallel does not exist or is not executable.")) {
    return '';
  }

  my $valid_output = CFX5::Commands::get_cmd_output($valid_exec, '-validate');
  return 1 unless ($valid_output =~ m/fail/i);

  # 2. Used when entering the username and password on the fly
  #    when prompted during a run and comprises the following registry keys:
  #   HKEY_CURRENT_USER\Software\Intel\MPI\HYDRA\CACHE\smpda
  #   HKEY_CURRENT_USER\Software\Intel\MPI\HYDRA\CACHE\smpdp
  # Note: mpiexec.exe -validate does not recognize this entry!
  #       Therefore, if (1) fails, check the registry.
  cfx5_require('CFX5::Win32::Registry') or return '';
  my $smpda = CFX5::Win32::Registry::registry_get('Software/Intel/MPI/HYDRA/CACHE/smpda');
  return 1 if (defined $smpda);

  # If we get this far, the check has failed. Issue an error message.
  _error("The Intel MPI hydra service is not running and/or no user credentials have been registered. The output given by $valid_exec was:\n\n$valid_output\n\nEither:\n\n1. Install Intel MPI using the ANSYS Installer, caching the password as per the installation instructions. CFX must then be restarted.\n\n2. Alternatively, configure MPI using the commands:\n\ncfx5parallel -install-impi-service\n\ncfx5parallel -register-impi-user");
  return '';
}

1;
