GRID-Machine

 view release on metacpan or  search on metacpan

TODO  view on Meta::CPAN


    and the other a farm/master-worker sub

  - divide and conquer and b&b: what to push? the result may imply new calls
                push @result, ($t{0+$me}, $me->_get_result()); 

                implement sort and other d&c examples
  - allow Inline::C java, python and others making room for heterogenous programming

  - fault tolerance: once there are no more  tasks to send, poll - from time to time -
    the machines to see if the remote processes are alive. If not, resend the problem/job
    to another alive machine
  - From time to time, store the results in the result file, provide a recover parameter allowing
    the recovery from a failure

* take from GRID::Cluster the automatic authentication installator

* I'm trying to see how IPC::PerlSSH behaves in case the underlying ssh connection gets disconnected.
  http://www.perlmonks.org/?node_id=792383

* Write an example of remotelibs in the constructor

examples/async1.pl  view on Meta::CPAN

   print "stdout: Hello from process $$. args = (@_)\n";
   print STDERR "stderr: Hello from process $$\n";

   use List::Util qw{sum};
   return { s => sum(@_), args => [ @_ ] };
});

my $p = $machine->async( hi => 1..4 );

# GRID::Machine::Process objects are overloaded
print "Doing something while $p is still alive  ...\n" if $p; 

my $r = $machine->waitall();

print "Result from process '$p': ",Dumper($r),"\n";
print "GRID::Machine::Process::Result objects are overloaded in a string context:\n$r\n";

examples/async2.pl  view on Meta::CPAN


$machine->sub(add => q{
   use List::Util qw{min};
   return  min(@_);
});

my $p  = $machine->async( sum  =>  1..4 );
my $p1 = $machine->async( add =>  7, 2, 9, 8, -1, 4 );

# GRID::Machine::Process objects are overloaded
print "Doing something while $p and $p1 are still alive  ...\n" if ($p and $p1); 

my $r = $machine->waitall()->result;

print "Result from process: $r\n";

$r = $machine->waitall()->result;
print "Result from process: $r\n";

examples/fork5.pl  view on Meta::CPAN

   print "stdout: Hello from process $$. args = (@_)\n";
   print STDERR "stderr: Hello from process $$\n";

   use List::Util qw{sum};
   return { s => sum(@_), args => [ @_ ] };
 },
 args => [ 1..4 ],
);

# GRID::Machine::Process objects are overloaded
print "Doing something while $p is still alive  ...\n" if $p; 

my $r = $machine->waitpid($p);

print "Result from process '$p': ",Dumper($r),"\n";
print "GRID::Machine::Process::Result objects are overloaded in a string context:\n$r\n";

examples/syntaxerr2.pl  view on Meta::CPAN

use Data::Dumper;

my $machine = GRID::Machine->new(host => 'casiano@orion.pcg.ull.es');

my $p = { name => 'Peter', familyname => [ 'Smith', 'Garcia'] };

my $r = $machine->eval( q{ $q = shift; $q->{familyname} }, $p);

die  Dumper($r) unless $r->ok;

print "Still alive\n";

examples/syntaxerr6.pl  view on Meta::CPAN

use Data::Dumper;

my $machine = GRID::Machine->new(host => 'casiano@orion.pcg.ull.es');

my $p = { name => 'Peter', familyname => [ 'Smith', 'Garcia'] };

my $r = $machine->sub(chuchu => q{ $q = shift; $q->{familyname} });

die  Dumper($r) unless $r->ok;

print "Still alive\n";

examples/wait1.pl  view on Meta::CPAN

   print "stdout: Hello from process $$. args = (@_)\n";
   print STDERR "stderr: Hello from process $$\n";

   use List::Util qw{sum};
   return { s => sum(@_), args => [ @_ ] };
 },
 args => [ 1..4 ],
);

# GRID::Machine::Process objects are overloaded
print "Doing something while $p is still alive  ...\n" if $p; 

my $r = $machine->waitall();

print "Result from process '$p': ",Dumper($r),"\n";
print "GRID::Machine::Process::Result objects are overloaded in a string context:\n$r\n";

examples/wait2.pl  view on Meta::CPAN

);

my $p1 = $machine->fork( q{
   use List::Util qw{sum};
   return { s => sum(@_), args => [ @_ ] };
 },
 args => [ 1..9 ],
);

# GRID::Machine::Process objects are overloaded
print "Doing something while $p is still alive  ...\n" if $p; 

my $r = $machine->waitall();

print "Result object from process:\n",Dumper($r),"\n";
print "GRID::Machine::Process::Result objects are overloaded in a string context:\n$r\n";

$r = $machine->waitall();

print "Result from process:\n",Dumper($r),"\n";
print "GRID::Machine::Process::Result objects are overloaded in a string context:\n$r\n";

lib/GRID/Machine.pod  view on Meta::CPAN

     4  use Data::Dumper;
     5  
     6  my $machine = GRID::Machine->new(host => 'user@machine.domain.es');
     7  
     8  my $p = { name => 'Peter', familyname => [ 'Smith', 'Garcia'] };
     9  
    10  my $r = $machine->eval( q{ $q = shift; $q->{familyname} }, $p);
    11  
    12  die  Dumper($r) unless $r->ok;
    13  
    14  print "Still alive\n";


When executed this code produces something like:

  $VAR1 = bless( {
                 'stderr' => '',
                 'errmsg' => 'user@machine.domain.es: Error while compiling eval \'$q = shift; $q->{fam...\'
                  Global symbol "$q" requires explicit package name at syntaxerr2.pl line 10, <STDIN> line 230.
                  Global symbol "$q" requires explicit package name at syntaxerr2.pl line 10, <STDIN> line 230.',
                 'type' => 'DIED',

lib/GRID/Machine.pod  view on Meta::CPAN

    11     print "stdout: Hello from process $$. args = (@_)\n";
    12     print STDERR "stderr: Hello from process $$\n";
    13  
    14     use List::Util qw{sum};
    15     return { s => sum(@_), args => [ @_ ] };
    16   },
    17   args => [ 1..4 ],
    18  );
    19  
    20  # GRID::Machine::Process objects are overloaded
    21  print "Doing something while $p is still alive  ...\n" if $p; 
    22  
    23  my $r = $machine->waitpid($p);
    24  
    25  print "Result from process '$p': ",Dumper($r),"\n";
    26  print "GRID::Machine::Process::Result objects are overloaded in a string context:\n$r\n";


When executed, the former program produces an output similar to this:

  $ perl fork5.pl 
  Doing something while 5220:5230:some.machine:5234:5237 is still alive  ...
  Result from process '5220:5230:some.machine:5234:5237': $VAR1 = bless( {
                   'machineID' => 0,
                   'stderr' => 'stderr: Hello from process 5237
  ',
                   'descriptor' => 'some.machine:5234:5237',
                   'status' => 0,
                   'waitpid' => 5237,
                   'errmsg' => '',
                   'stdout' => 'stdout: Hello from process 5237. args = (1 2 3 4)
  ',

lib/GRID/Machine.pod  view on Meta::CPAN


The arguments for the code executed by the remote child process

=back

=head2 C<GRID::Machine::Process> objects

L<GRID::Machine::Process> objects have been overloaded. In a string context 
a L<GRID::Machine::Process> object 
produces the concatenation C<hostname:clientPID:remotePID>. 
In a boolean context it returns true if the process is alive and false otherwise.
This way, the execution of line 21 in the program above:

    21  print "Doing something while $p is still alive  ...\n" if $p; 

produces an output like:

  Doing something while 5220:5230:some.machine:5234:5237 is still alive  ...

if the remote process is still alive. The descriptor of the process
C<5220:5230:some.machine:5234:5237>
is a colon separated sequence of five components:

=over 2

=item 1 - The PID of the local process executing L<GRID::Machine> 

=item 2 - The PID of the local process in charge of the connection with the remote 
machine

=item 3 - The name of the remote machine 

=item 4 - The PID of the remote process executing L<GRID::Machine::REMOTE>

=item 5 - The PID of the child process created by C<fork>

=back

When evaluated in a boolean context, a L<GRID::Machine::Process> returns
1 if it is alive and 0 otherwise.

=head2 The C<waitpid> method

The C<waitpid> method  waits for the L<GRID::Machine::Process> received as first argument 
to terminate. Additional C<FLAGS> as in perl C<waitpid> can be passed as arguments.
It returns a L<GRID::Machine::Process::Result> object, whose attributes contain:


=over 2 

lib/GRID/Machine.pod  view on Meta::CPAN

    11     print "stdout: Hello from process $$. args = (@_)\n";
    12     print STDERR "stderr: Hello from process $$\n";
    13  
    14     use List::Util qw{sum};
    15     return { s => sum(@_), args => [ @_ ] };
    16   },
    17   args => [ 1..4 ],
    18  );
    19  
    20  # GRID::Machine::Process objects are overloaded
    21  print "Doing something while $p is still alive  ...\n" if $p; 
    22  
    23  my $r = $machine->waitall();
    24  
    25  print "Result from process '$p': ",Dumper($r),"\n";
    26  print "GRID::Machine::Process::Result objects are overloaded in a string context:\n$r\n";

When executed produces:

  $ perl wait1.pl 
  Doing something while 1271:1280:local:1284:1287 is still alive  ...
  Result from process '1271:1280:local:1284:1287': $VAR1 = bless( {
                   'machineID' => 0,
                   'stderr' => 'stderr: Hello from process 1287
  ',
                   'descriptor' => 'local:1284:1287',
                   'status' => 0,
                   'waitpid' => 1287,
                   'errmsg' => '',
                   'stdout' => 'stdout: Hello from process 1287. args = (1 2 3 4)
  ',

lib/GRID/Machine/Process.pm  view on Meta::CPAN

  use warnings;
  use strict;
  use GRID::Machine::MakeAccessors; 

  my @legal = qw(machine pid stdin stdout stderr result);
  my %legal = map { $_ => 1 } @legal;

  GRID::Machine::MakeAccessors::make_accessors(@legal);

  use overload q("") => 'str',
               bool  => 'alive';

  sub waitpid {
   my $self = shift;

   my $machine = $self->machine;
   
   #delegate
   $machine->waitpid($self, @_);
  }

lib/GRID/Machine/Process.pm  view on Meta::CPAN


    my $machine = $self->machine;

    "$$".$separator.
    $machine->{pid}.$separator.
    $machine->host.$separator.
    $machine->getpid.$separator.
    $self->pid;
  }

  sub alive {
    my $self = shift;

    my $pid = $self->{pid};
    $self->{machine}->poll($pid);
  }
}

{
  package GRID::Machine::Process::Result;
  use warnings;

lib/GRID/Machine/Process.pod  view on Meta::CPAN

    11     print "stdout: Hello from process $$. args = (@_)\n";
    12     print STDERR "stderr: Hello from process $$\n";
    13  
    14     use List::Util qw{sum};
    15     return { s => sum(@_), args => [ @_ ] };
    16   },
    17   args => [ 1..4 ],
    18  );
    19  
    20  # GRID::Machine::Process objects are overloaded
    21  print "Doing something while $p is still alive  ...\n" if $p; 
    22  
    23  my $r = $machine->waitpid($p);
    24  
    25  print "Result from process '$p': ",Dumper($r),"\n";
    26  print "GRID::Machine::Process::Result objects are overloaded in a string context:\n$r\n";


When executed, the former program produces an output similar to this:

  $ perl fork5.pl 
  Doing something while 5220:5230:some.machine:5234:5237 is still alive  ...
  Result from process '5220:5230:some.machine:5234:5237': $VAR1 = bless( {
                   'machineID' => 0,
                   'stderr' => 'stderr: Hello from process 5237
  ',
                   'descriptor' => 'some.machine:5234:5237',
                   'status' => 0,
                   'waitpid' => 5237,
                   'errmsg' => '',
                   'stdout' => 'stdout: Hello from process 5237. args = (1 2 3 4)
  ',

lib/GRID/Machine/Process.pod  view on Meta::CPAN


The arguments for the code executed by the remote child process

=back

=head2 C<GRID::Machine::Process> objects

L<GRID::Machine::Process> objects have been overloaded. In a string context 
a L<GRID::Machine::Process> object 
produces the concatenation C<hostname:clientPID:remotePID>. 
In a boolean context it returns true if the process is alive and false otherwise.
This way, the execution of line 21 in the program above:

    21  print "Doing something while $p is still alive  ...\n" if $p; 

produces an output like:

  Doing something while 5220:5230:some.machine:5234:5237 is still alive  ...

if the remote process is still alive. The descriptor of the process
C<5220:5230:some.machine:5234:5237>
is a colon separated sequence of five components:

=over 2

=item 1 - The PID of the local process executing L<GRID::Machine> 

=item 2 - The PID of the local process in charge of the connection with the remote 
machine

=item 3 - The name of the remote machine 

=item 4 - The PID of the remote process executing L<GRID::Machine::REMOTE>

=item 5 - The PID of the child process created by C<fork>

=back

When evaluated in a boolean context, a L<GRID::Machine::Process> returns
1 if it is alive and 0 otherwise.

=head2 The C<waitpid> method

The C<waitpid> method  waits for the L<GRID::Machine::Process> received as first argument 
to terminate. Additional C<FLAGS> as in perl C<waitpid> can be passed as arguments.
It returns a L<GRID::Machine::Process::Result> object, whose attributes contain:


=over 2 

lib/GRID/Machine/Process.pod  view on Meta::CPAN

    11     print "stdout: Hello from process $$. args = (@_)\n";
    12     print STDERR "stderr: Hello from process $$\n";
    13  
    14     use List::Util qw{sum};
    15     return { s => sum(@_), args => [ @_ ] };
    16   },
    17   args => [ 1..4 ],
    18  );
    19  
    20  # GRID::Machine::Process objects are overloaded
    21  print "Doing something while $p is still alive  ...\n" if $p; 
    22  
    23  my $r = $machine->waitall();
    24  
    25  print "Result from process '$p': ",Dumper($r),"\n";
    26  print "GRID::Machine::Process::Result objects are overloaded in a string context:\n$r\n";

When executed produces:

  $ perl wait1.pl 
  Doing something while 1271:1280:local:1284:1287 is still alive  ...
  Result from process '1271:1280:local:1284:1287': $VAR1 = bless( {
                   'machineID' => 0,
                   'stderr' => 'stderr: Hello from process 1287
  ',
                   'descriptor' => 'local:1284:1287',
                   'status' => 0,
                   'waitpid' => 1287,
                   'errmsg' => '',
                   'stdout' => 'stdout: Hello from process 1287. args = (1 2 3 4)
  ',

lib/GRID/Machine/REMOTE.pm  view on Meta::CPAN

  do {
    $deceased = waitpid($process->{pid}, @_ ? @_ : 0);
    $status = $?;

    #gprint("Synchronized: Pid of the deceased process: $deceased\n");
    #gprint("there are processes still running\n") if (!$deceased);

    #SERVER->remotelog("deceased = $deceased");

    #if (kill 0, -$process->{pid}) { gprint("Not answer to 0 signal from process $process->{pid}\n") }
    #else { gprint("Strange: the process $process->{pid} is still alive\n"); }

  } while (kill 0, $process->{pid});

  # if deceased is 0
  # TODO: study flock, may be this way we can synchronize!!

  delete $process{$deceased} if $deceased > 0;

  local $/ = undef;
  open my $fo, $process->{stdout}; # check exists, die, etc.

lib/GRID/Machine/REMOTE.pm  view on Meta::CPAN

    $deceased = CORE::wait();
    $status = $?;

    return $deceased if ($deceased <= 0);
    #gprint("Synchronized: Pid of the deceased process: $deceased\n");
    #gprint("there are processes still running\n") if (!$deceased);

    #SERVER->remotelog("deceased = $deceased");

    #if (kill 0, -$process->{pid}) { gprint("Not answer to 0 signal from process $process->{pid}\n") }
    #else { gprint("Strange: the process $process->{pid} is still alive\n"); }

  } while (kill 0, $deceased);


  # if deceased is 0
  # TODO: study flock, may be this way we can synchronize!!

  my $process = $process{$deceased};
  delete $process{$deceased};



( run in 1.656 second using v1.01-cache-2.11-cpan-39bf76dae61 )