=head1 NAME

  CFX5::Parallel::Reqs::appfile - appfile generator for CFX-5 parallel

$Id$

=cut

package CFX5::Parallel::Reqs::appfile;

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

use CFX5::Config qw(%Config);
use CFX5::Output qw(:all);

use CFX5::PkgLoader qw(cfx5_require);

use CFX5::FileOps qw(append_to_file);

use strict;

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

  my @lines;

  # first, get the text to put in the appfile from the start method
  my $sm=$self->ppe()->start_method();
  my $host_entry=$sm->appfile_host_entry();

  # sort out the header
  {
    my $header=$sm->appfile_header();
    if (defined $header) {
      $header=$sm->fill_shared_template($header, $self->ppe());
      $header=$sm->fill_host_template($header, $self->ppe(), 1, $self->ppe()->master_host(), 'yes this is the master');
      $sm->assert_fully_replaced($header)
        or return undef;
      push @lines, "$header\n";
    }
  }

  # fill in shared parts of the host entry line already
  $host_entry=$sm->fill_shared_template($host_entry, $self->ppe());

  # We need to consolidate partitions on the same host, to get
  # efficient use of shared memory machines, but we also need to
  # preserve the order of the hosts in the list so that any
  # non-uniform partition sizes are assigned to the correct hosts.
  my @hosts=$self->ppe()->partitions_master_first();

  # the master host gets a special entry for the first partition on
  # it, to tell it not to start any further processes.  If we can't
  # find it, this loop will not notice, but the
  # partitions_master_first call above will already have errored.

  my $found_master='';

  for my $h (@hosts) {
    # shared memory allowed for this host - we decrement the count
    # by one for the master, but otherwise as normal
    my $c=$h->[0];
    if (!$found_master and $self->ppe()->is_master($h->[1])) {
      #$c--;
      $found_master++;
    }
    my $l=$sm->fill_host_template($host_entry, $self->ppe(), $c,$h->[1], 0);

    $sm->assert_fully_replaced($l);
    push @lines, $l, "\n";
  }

  # we always remove and re-write
  $workdir->remove_file('appfile') if $workdir->have_file('appfile');
  my $file=$workdir->creatable_file('appfile');
  unless (append_to_file($file, @lines)) {
    _error("Error writing appfile: $!");
    return undef;
  }

  $self->{__PACKAGE__ . '::filename'}=$file;
}

sub get_replacement_text {
  my $self=shift;
  $self->{__PACKAGE__ . '::filename'};
}

1;
